using Fab2ApprovalSystem.DMO;
using Fab2ApprovalSystem.Models;
using Fab2ApprovalSystem.ViewModels;
using Fab2ApprovalSystem.Utilities;
using Kendo.Mvc.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Kendo.Mvc.Extensions;
using Fab2ApprovalSystem.Misc;
using System.Configuration;


namespace Fab2ApprovalSystem.Controllers
{
    [Authorize]
    [SessionExpireFilter]
    public class TrainingController : Controller
    {
        UserAccountDMO userDMO = new UserAccountDMO();
        AdminDMO adminDMO = new AdminDMO();
        TrainingDMO trainingDMO = new TrainingDMO();
        ECN_DMO ecnDMO = new ECN_DMO();
        public EmailUtilities emailer = new EmailUtilities();

        // GET: Training
        public ActionResult Index()
        {
            return View();
        }
        //public int Create(int ecnId, List<int> groupIds)
        public int Create(int ecnId)
        {
            ECN_DMO ecnDMO = new ECN_DMO();

            //Delete old training if exists
            int oldTrainingId = trainingDMO.GetTrainingId(ecnId);
            if (oldTrainingId != null && oldTrainingId != 0)
            {
                trainingDMO.DeleteTraining(oldTrainingId);
            }


            int trainingId = trainingDMO.Create(ecnId);
            List<int> TrainingGroups = new List<int>();
            TrainingGroups = trainingDMO.GetECNAssignedTrainingGroups(ecnId);
            string ECNTitle = ecnDMO.GetECN(ecnId).Title;
            List<int> Trainees = new List<int>();
            foreach (var group in TrainingGroups)
            {
                Trainees.AddRange(trainingDMO.GetTrainees(group));
            }
            Trainees = (from a in Trainees select a).Distinct().ToList();

            foreach (var trainee in Trainees)
            {
                int assignmentId = trainingDMO.CreateAssignment(trainingId, trainee);
                NotifyTrainee(trainee, assignmentId, ecnId, ECNTitle);
            }


            return trainingId;
        }
        public ActionResult AddUserToTrainingAdHoc(int trainingId, int traineeId, int ecnId)
        {
            if ((bool)Session[GlobalVars.IS_ADMIN])
            {
                //Get ECN
                ECN ecn = ecnDMO.GetECN(ecnId);

                //Get User
                LoginModel user = userDMO.GetUserByID(traineeId);

                //Get Training
                Training training = trainingDMO.GetTraining(trainingId);
                if (ecn != null)
                {
                    if (user != null)
                    {
                        if (training != null)
                        {
                            if (!trainingDMO.IsUserAssigned(traineeId, trainingId))
                            {
                                if (training.DeletedDate == null && !ecn.Deleted)
                                {
                                    //Both the ECN and training still exist
                                    if (training.CompletedDate != null)
                                    {
                                        //Training is completed and now we need to re-open it.
                                        trainingDMO.reOpenTraining(trainingId);
                                        int assignmentId = trainingDMO.CreateAssignment(trainingId, traineeId);
                                        NotifyTrainee(traineeId, assignmentId, ecnId, ecn.Title);
                                        return Content("Success");
                                    }
                                    else
                                    {
                                        //training is still open, just add a user and notify
                                        int assignmentId = trainingDMO.CreateAssignment(trainingId, traineeId);
                                        NotifyTrainee(traineeId, assignmentId, ecnId, ecn.Title);
                                        return Content("Success");
                                    }
                                }
                                else
                                {
                                    //Ecn or training task have been deleted.
                                    return Content("Training or ECN has been deleted.");
                                }
                            }
                            else
                            {
                                return Content("User already has an open or completed assignment for this training.");
                            }

                        }
                        else
                        {
                            return Content("Invalid training id.");
                        }
                    }
                    else
                    {
                        return Content("invalid userId");
                    }
                }
                else
                {
                    return Content("ECN invalid");
                }
            }
            else
            {
                return Content("Not Authorized");
            }
            
        
        }
        public ActionResult AddGroupToTrainingAdHoc(int trainingId, int groupId, int ecnId)
        {
            if ((bool)Session[GlobalVars.IS_ADMIN])
            {
                ECN ecn = ecnDMO.GetECN(ecnId);
                Training training = trainingDMO.GetTraining(trainingId);
                TrainingGroup group = trainingDMO.GetTrainingGroupByID(groupId);
                List<int> groupMemberIds = trainingDMO.GetTrainees(groupId);
                int usersAdded = 0;

                if (ecn != null)
                {
                    if (training != null)
                    {
                        if (training.DeletedDate == null && !ecn.Deleted)
                        {
                            if (training.CompletedDate != null)
                            {
                                //Training is completed and now we need to re-open it.
                                foreach (int id in groupMemberIds)
                                {
                                    //Check to make sure user doesn't have an active assignment for this training
                                    if (!trainingDMO.IsUserAssigned(id, trainingId))
                                    {
                                        usersAdded++;
                                        int assignmentId = trainingDMO.CreateAssignment(trainingId, id);
                                        NotifyTrainee(id, assignmentId, ecnId, ecn.Title);
                                    }

                                }
                                if (usersAdded > 0)
                                {
                                    trainingDMO.reOpenTraining(trainingId);
                                }

                            }
                            else
                            {
                                //training is still open, just add a users and notify
                                foreach (int id in groupMemberIds)
                                {
                                    //Check to make sure user doesn't have an active assignment for this training
                                    if (!trainingDMO.IsUserAssigned(id, trainingId))
                                    {
                                        usersAdded++;
                                        int assignmentId = trainingDMO.CreateAssignment(trainingId, id);
                                        NotifyTrainee(id, assignmentId, ecnId, ecn.Title);
                                    }
                                }
                            }
                            if(usersAdded > 0)
                            {
                                try
                                {
                                    trainingDMO.AddTrainingGroupToECN(ecnId, groupId);
                                }
                                catch(Exception e)
                                {
                                    return Content(e.ToString());
                                }
                            }
                            return Content("Success. " + usersAdded + " users added.");
                        }
                        else
                        {
                            return Content("Training or ECN has been deleted.");
                        }
                    }
                    else
                    {
                        return Content("Invalid training id.");
                    }
                }
                else
                {
                    return Content("ECN invalid");
                }
            }
            else
            {
                return Content("Not Authorized");
            }
            
            
        }
        public ActionResult DeleteTrainingByECN(int ECNNumber)
        {
            int trainingId = trainingDMO.GetTrainingId(ECNNumber);
            if (trainingId != null && trainingId != 0)
            {
                trainingDMO.DeleteTraining(trainingId);
            }
            return RedirectToAction("ViewTrainings");
        }

        public ActionResult DeleteTrainingByID(int trainingId)
        {
            if (trainingId != null && trainingId != 0)
            {
                trainingDMO.DeleteTraining(trainingId);
            }
            return RedirectToAction("ViewTrainings");
        }
        public void NotifyTrainee(int userId, int assignmentId, int ecnId, string title)
        {

            try
            {
                string emailSentList = "";
                //ECN ecn = ecnDMO.GetECN(ecnNumber);
                //List<string> emailIst = ldDMO.GetApproverEmailList(@issueID, currentStep).Distinct().ToList();
                string recipient = userDMO.GetUserEmailByID(userId.ToString());

                string emailTemplate = "ECNTrainingAssigned.txt";
                string userEmail = string.Empty;
                string subject = string.Empty;
                string senderName = "ECN Training";

                subject = "ECN# " + ecnId + " - Training Assignment Notice - " + title;

                    EmailNotification en = new EmailNotification(subject, ConfigurationManager.AppSettings["EmailTemplatesPath"]);
                    //string emailparams = "";
                    userEmail = recipient;
                    string[] emailparams = new string[4];
                    emailparams[0] = assignmentId.ToString();
                    emailparams[1] = ecnId.ToString();
                    emailparams[2] = GlobalVars.hostURL;
                //#if(DEBUG)
                //string SenderEmail = "MesaFabApproval@infineon.com";
                //userEmail = "jonathan.ouellette@infineon.com";
                //#endif

                en.SendNotificationEmail(emailTemplate, GlobalVars.SENDER_EMAIL, senderName, userEmail, null, subject, emailparams);
                    //en.SendNotificationEmail(emailTemplate, SenderEmail, senderName, userEmail, null, subject, emailparams);
            }
            catch (Exception e)
            {
                string detailedException = "";
                try
                {
                    detailedException = e.InnerException.ToString();
                }
                catch
                {
                    detailedException = e.Message;
                }
            }


        }
        public ActionResult ViewTrainingPartial(int trainingID, int userID)
        {
            List<TrainingAssignment> TrainingData = trainingDMO.GetTrainingAssignmentsByUser(trainingID, userID);
            if (trainingID > 0)
            {
                ViewBag.ECNNumber = trainingDMO.GetTraining(trainingID).ECN;
            }
            return PartialView(TrainingData);
        }
        public ActionResult ViewTrainingDocsPartial(int trainingAssignmentId)
        {
            ViewBag.trainingAssignmentId = trainingAssignmentId;
            //IEnumerable<TrainingDocAck> attachments = ecnDMO.GetECNAttachments(ecnNumber);
            IEnumerable<TrainingDocAck> attachments = trainingDMO.GetAssignedDocs(trainingAssignmentId);
            return PartialView(attachments);
        }
        public ActionResult AcknowledgeDocument(int trainingAssignmentID, int trainingDocAckID)
        {
            //Check to see if acknowledgement is valid(Security Feature to protect data integrity)
            if (trainingDMO.CheckValidDocAck(trainingDocAckID))
            {
                trainingDMO.AcknowledgeDocument(trainingDocAckID);
                bool isFinishedTrainingAssignment = trainingDMO.CheckTrainingAssignmentStatus(trainingAssignmentID);

                if (isFinishedTrainingAssignment)
                {
                    try
                    {
                        trainingDMO.UpdateAssignmentStatus(trainingAssignmentID);
                        bool isFinishedTraining = trainingDMO.CheckTrainingStatus(trainingAssignmentID);
                        if (isFinishedTraining)
                        {
                            int TrainingID = trainingDMO.GetTrainingIdByAssignment(trainingAssignmentID);
                            trainingDMO.UpdateTrainingStatus(TrainingID);
                        }
                    }
                    catch (Exception e)
                    {
                        string exception = e.ToString();
                        return Content(exception);
                    }



                }
            }

            return Content("Marked Succesfully.");
        }
        public ActionResult AcknowledgeReviewNoDocuments(int trainingAssignmentID)
        {
            try
            {
                trainingDMO.UpdateAssignmentStatus(trainingAssignmentID);
                bool isFinishedTraining = trainingDMO.CheckTrainingStatus(trainingAssignmentID);
                if (isFinishedTraining)
                {
                    int TrainingID = trainingDMO.GetTrainingIdByAssignment(trainingAssignmentID);
                    trainingDMO.UpdateTrainingStatus(TrainingID);
                }
            }
            catch (Exception e)
            {
                string exception = e.ToString();
                return Content(exception, "application/json");
            }

            return Json(new { test = "Succesfully saved" });
        }
        //public ActionResult ViewTrainings()
        //{
        //    IEnumerable<Training> trainings = trainingDMO.GetTrainings();

        //    return View(trainings);
        //}
        public ActionResult TrainingReports()
        {

            return View();
        }
        public ActionResult TrainingReportsView(int? filterType, string filterValue)
        {
            ViewBag.TrainingGroups = adminDMO.GetTrainingGroups();
            IEnumerable<Training> trainingList = trainingDMO.GetAllTrainings();
            //Group Filter
            if (filterType == 1 && filterValue != "")
            {
                ViewBag.GroupFilter = filterValue;
                List<Training> filteredTraining = new List<Training>();
                foreach (var item in trainingList)
                {
                    List<int> assignedTrainingGroups = trainingDMO.GetECNAssignedTrainingGroups(item.ECN);
                    foreach (int id in assignedTrainingGroups)
                    {
                        if (filterValue == id.ToString())
                        {
                            filteredTraining.Add(item);
                        }
                    }
                }
                trainingList = filteredTraining;
                return PartialView(trainingList);
            }
            //Status Filter
            if (filterType == 2 && filterValue != "")
            {
                List<Training> filteredTraining = new List<Training>();
                switch (filterValue)
                {
                    case "1":
                        //Completed
                        filteredTraining = (from a in trainingList where a.Status == true && a.Deleted != true select a).ToList();
                        break;
                    case "2":
                        //In Progress
                        filteredTraining = (from a in trainingList where a.Status != true && a.Deleted != true select a).ToList();
                        break;
                    case "3":
                        //Cancelled
                        filteredTraining = (from a in trainingList where a.Deleted == true select a).ToList();
                        break;
                }
                trainingList = filteredTraining;
                return PartialView(trainingList);
            }
            //Default return all.
            else
            {
                return PartialView(trainingList);
            }
            
            
            
        }
        public ActionResult ViewTrainingAssignmentsReportView(int trainingID, string statusFilter, string groupFilter)
        {
            bool? trainingStatus = trainingDMO.GetTraining(trainingID).Status;
            int ECNNumber = trainingDMO.GetTraining(trainingID).ECN;
            string ECNTitle = ecnDMO.GetECN(ECNNumber).Title;
            ViewBag.TrainingGroups = adminDMO.GetTrainingGroups();
            ViewBag.TrainingStatus = trainingStatus;
            ViewBag.ECNNumber = ECNNumber;
            ViewBag.ECNTitle = ECNTitle;
            ViewBag.trainingID = trainingID;
            IEnumerable<TrainingAssignment> trainingAssignments = trainingDMO.GetAllTrainingAssignments(trainingID);
            //Calculate Percent Complete:
            float percentComplete = 0;
            //float assignmentCount = trainingAssignments.Count();
            float assignmentCount = (from a in trainingAssignments where a.Deleted != true select a).Count();
            float totalCompleted = 0;
            foreach (var assignment in trainingAssignments)
            {
                if (assignment.status == true && assignment.Deleted != true)
                {
                    totalCompleted++;
                }
            }
            percentComplete = (totalCompleted / assignmentCount) * 100;
            ViewBag.PercentComplete = percentComplete.ToString("0.00") + "%";
           
            if (groupFilter != "" && groupFilter != null)
            {
                ViewBag.GroupFilter = groupFilter;
                List<TrainingAssignment> groupFilteredTraining = new List<TrainingAssignment>();
                List<int> groupMemberIds = trainingDMO.GetTrainees(Convert.ToInt32(groupFilter));
                foreach (var assignment in trainingAssignments)
                {
                    if(trainingDMO.isUserTrainingMember(Convert.ToInt32(groupFilter), assignment.UserID))
                    {
                        groupFilteredTraining.Add(assignment);
                    }
                }
                trainingAssignments = groupFilteredTraining;

            }
            if (statusFilter != "" && statusFilter != null)
            {
                List<TrainingAssignment> filteredTraining = new List<TrainingAssignment>();
                switch (statusFilter)
                {
                    
                    case "1":
                        //Completed
                        filteredTraining = (from a in trainingAssignments where a.status == true && a.Deleted != true select a).ToList();
                        break;
                    case "2":
                        //In Progress
                        filteredTraining = (from a in trainingAssignments where a.status != true && a.Deleted != true select a).ToList();
                        break;
                    case "3":
                        //Cancelled
                        filteredTraining = (from a in trainingAssignments where a.Deleted == true select a).ToList();
                        break;
                    default:
                        filteredTraining = (from a in trainingAssignments select a).ToList();
                        break;
                }
                trainingAssignments = filteredTraining;
                //return PartialView(trainingList);
            }

            return PartialView(trainingAssignments);
        }
        public ActionResult ViewTrainingAssignments(int trainingID)
        {
            bool? trainingStatus = trainingDMO.GetTraining(trainingID).Status;
            int ECNNumber = trainingDMO.GetTraining(trainingID).ECN;
            string ECNTitle = ecnDMO.GetECN(ECNNumber).Title;
            ViewBag.TrainingStatus = trainingStatus;
            ViewBag.ECNNumber = ECNNumber;
            ViewBag.ECNTitle = ECNTitle;
            ViewBag.TrainingId = trainingID;
            ViewBag.AllUsers = userDMO.GetAllActiveUsers();
            ViewBag.AllGroups = trainingDMO.GetTrainingGroups();
            IEnumerable<TrainingAssignment> trainingAssignments = trainingDMO.GetTrainingAssignments(trainingID);
            
            return View(trainingAssignments);
        }
        /// <summary>
        /// Method to return all the training assignments for a specified user
        /// </summary>
        /// <param name="userID"></param>
        /// <returns></returns>
        public ActionResult ViewMyTrainingAssignments()
        {
            int userID = (int)Session[GlobalVars.SESSION_USERID];
            List<TrainingAssignment> assignments = trainingDMO.GetTrainingAssignmentsByUserID(userID);
            List<ECNTrainingAssignments> ViewData = new List<ECNTrainingAssignments>();
            foreach (var assignment in assignments)
            {
                Training training = trainingDMO.GetTraining(assignment.TrainingID);
                if (training != null && !assignment.status)
                {
                    int ecnID = training.ECN;
                    ViewData.Add(new ECNTrainingAssignments
                    {
                        TrainingAssignmentID = assignment.ID,
                        ECN_ID = ecnID,
                        TrainingID = assignment.TrainingID,
                        DateAssigned = assignment.DateAssigned,
                        DateCompleted = assignment.DateCompleted,
                        Status = assignment.status


                    });
                }

            }

            return View(ViewData);
        }
        /// <summary>
        /// Method to return all assigned documents for a specified training assignment
        /// </summary>
        /// <param name="assignmentID"></param>
        /// <returns></returns>
        public ActionResult ViewMyTrainingAssignment(int assignmentID, int ECNNumber)
        {
            ViewBag.ECNNumber = ECNNumber;
            ViewBag.AssignmentID = assignmentID;
            ViewBag.IsCompleted = trainingDMO.GetAssignment(assignmentID).status;
            return View(trainingDMO.GetAssignedDocs(assignmentID));
        }
        public ActionResult ViewTrainings(int? filterType, string filterValue)
        {
            IEnumerable<Training> AllTrainings = trainingDMO.GetTrainings();
            ViewBag.TrainingGroups = adminDMO.GetTrainingGroups();
            ViewBag.AllGroups = trainingDMO.GetTrainingGroups();
            //Group Filter
            if (filterType == 1 && filterValue != "")
            {
                ViewBag.GroupFilter = filterValue;
                List<Training> filteredTraining = new List<Training>();
                foreach (var item in AllTrainings)
                {
                    List<int> assignedTrainingGroups = trainingDMO.GetECNAssignedTrainingGroups(item.ECN);
                    foreach (int id in assignedTrainingGroups)
                    {
                        if (filterValue == id.ToString())
                        {
                            filteredTraining.Add(item);
                        }
                    }
                }
                AllTrainings = filteredTraining;
                return View(AllTrainings);
            }
            else
            {
                ViewBag.AllGroups = trainingDMO.GetTrainingGroups();
                return View(AllTrainings);
            }
            
           
        }
        public ActionResult ViewAllTrainings()
        {

            return View();
        }
        public ActionResult DeleteAssignment(int assignmentId)
        {
            trainingDMO.DeleteTrainingAssignment(assignmentId);
            trainingDMO.DeleteTrainingDocAck(assignmentId);

            //Below checks and updates the training status
            //TO-DO Put this in its own method.
            bool isFinishedTrainingAssignment = trainingDMO.CheckTrainingAssignmentStatus(assignmentId);

            if (isFinishedTrainingAssignment)
            {
                try
                {
                    trainingDMO.UpdateAssignmentStatus(assignmentId);
                    bool isFinishedTraining = trainingDMO.CheckTrainingStatus(assignmentId);
                    if (isFinishedTraining)
                    {
                        int TrainingID = trainingDMO.GetTrainingIdByAssignment(assignmentId);
                        trainingDMO.UpdateTrainingStatus(TrainingID);
                    }
                }
                catch (Exception e)
                {
                    string exception = e.ToString();
                    return Content(exception, "application/json");
                }



            }

            return Json(new { test = "Succesfully saved" });
        }
        public ActionResult ManuallyExecuteECNTraining(int ecnId, int[] trainingGroupsIn)
        {
            if ((bool)Session[GlobalVars.IS_ADMIN])
            {
                List<int> newTrainingGroupIds = new List<int>(trainingGroupsIn);
                //Get ECN
                ECN ecn = ecnDMO.GetECN(ecnId);
                if (ecn != null)
                {
                    if(ecn.CloseDate != null)
                    {
                        if (newTrainingGroupIds.Count > 0)
                        {
                            //Check each assigned group id and see if it's already saved to the ECN
                            List<int> assignedTrainingGroups = trainingDMO.GetECNAssignedTrainingGroups(ecnId);
                            IEnumerable<int> onlyNewTrainingIds = newTrainingGroupIds.Except(assignedTrainingGroups);
                            try
                            {
                                foreach (int trainingId in onlyNewTrainingIds)
                                {
                                    trainingDMO.AddTrainingGroupToECN(ecnId, trainingId);
                                }
                            
                                trainingDMO.SetTrainingFlag(ecnId);
                                Create(ecnId);
                                return Content("Success");
                            }
                            catch(Exception e)
                            {
                                return Content("Failed: " + e.Message.ToString());
                            }
                        }
                        else
                        {
                            return Content("There were no training groups to assign to. Please select at least one training groups.");
                        }

                    }
                    else
                    {
                        return Content("Selected ECN hasn't been approved yet.");
                    }
                }
                else
                {
                    return Content("Invalid ECN");
                }
            }
            else
            {
                return Content("Not Autthorized");
            }
        }
        public ActionResult CheckECN(int ecnId)
        {
            ECN ecn = ecnDMO.GetECN(ecnId);
            if(ecn != null)
            {
                if(ecn.CloseDate != null)
                {
                    List<int> trainingGroupIds = trainingDMO.GetECNAssignedTrainingGroups(ecnId);
                    List<TrainingGroup> assignedGroups = new List<TrainingGroup>();
                    foreach (int trainingGroupId in trainingGroupIds)
                    {
                        TrainingGroup trainingGroup = trainingDMO.GetTrainingGroupByID(trainingGroupId);
                        assignedGroups.Add(trainingGroup);
                    }
                    return Json(trainingGroupIds.ToList());
                }
                else
                {
                    return Content("ECN not yet approved.");
                }

            }
            else
            {
                return Content("That ECN wasn't found.");
            }

        }
        public bool RunTrainingReport()
        {
            bool isSuccess = false;
            try
            {
                string emailBody = "<h1>Mesa Approval Open Training Assignments Daily Report</h1> <br />";
                emailBody += "<p>The following contains open training assignments in the Mesa Approval system. Please ensure the following users complete their training assignments.</p><br />";
                emailBody += "<style>table,th,td{border: 1px solid black;}</style>";
                //Get all users set up to receive the training report email.
                List<TrainingReportUser> trainingReportUsers = adminDMO.GetTrainingReportUsers();
                List<string> emailList = new List<string>();
                foreach (var user in trainingReportUsers)
                {
                    string userEmail = userDMO.GetUserByID(user.UserId).Email;
                    emailList.Add(userEmail);
                }
                //emailList.Add("Jonathan.Ouellette@infineon.com");
                //Get a list of open trainings
                List<Training> openTrainings = trainingDMO.GetAllOpenTrainings();

                foreach (Training training in openTrainings)
                {
                    string ecnTitle = ecnDMO.GetECN(training.ECN).Title;
                    emailBody += "<h3>" + training.ECN + " - " + ecnTitle + "</h3>";

                    emailBody += "<table>";
                    emailBody += "<tr><th>Name</th><th>Date Assigned</th></tr>";
                    List<TrainingAssignment> openAssignments = trainingDMO.GetOpenAssignmentsByTrainingID(training.TrainingID);
                    foreach (TrainingAssignment assignment in openAssignments)
                    {
                        DateTime? assignmentDate = assignment.DateAssigned;

                        string DateAssigned = assignmentDate.HasValue ? assignmentDate.Value.ToString("MM/dd/yyyy") : "<not available>";

                        emailBody += "<tr><td>" + assignment.FullName + "</td><td>" + DateAssigned + "</td></tr>";

                    }
                    emailBody += "</table>";
                }
                string recipientEmail = "";
                List<string> ccRecipients = emailList;
                emailer.SendNotification("MesaFabApproval@infineon.com", ccRecipients, "Mesa Approval Daily Open Training Report", emailBody, "Daily Open Training Report");
                isSuccess = true;
            }
            catch
            {
                isSuccess = false;
            }
            return isSuccess;
        }
    }
    
}