using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using Fab2ApprovalSystem.DMO;
using Fab2ApprovalSystem.Misc;
using Fab2ApprovalSystem.Models;
using Fab2ApprovalSystem.Utilities;
using Fab2ApprovalSystem.ViewModels;

using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;

namespace Fab2ApprovalSystem.Controllers;

[Authorize]
[SessionExpireFilter]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class HomeController : Controller {

    MRB_DMO mrbDMO = new MRB_DMO(GlobalVars.AppSettings);
    PartsRequestDMO prDMO = new PartsRequestDMO();
    LotDispositionDMO ldDMO = new LotDispositionDMO();
    WorkflowDMO wfDMO = new WorkflowDMO();
    ECN_DMO ecnDMO = new ECN_DMO();
    UserUtilities userDMO = new UserUtilities();
    UserAccountDMO originalUserDMO = new UserAccountDMO();
    TrainingDMO trainingDMO = new TrainingDMO();
    MiscDMO miscDMO = new MiscDMO();
    private readonly AppSettings _AppSettings = GlobalVars.AppSettings;

    public ActionResult Index(string tabName) {
        ViewBag.ActiveTabName = tabName;

        return View();
    }

    public ActionResult MyTasks() {
        return View();
    }

    public ActionResult AllDocuments() {
        return View();
    }

    public ActionResult SpecialWorkRequestList() {
        return View();
    }

    public ActionResult MRBList() {
        return View();
    }

    public ActionResult ECNList() {
        return View();
    }
    public ActionResult TrainingList() {
        return View();
    }

    public ActionResult LotDispositionList() {
        return View();
    }

    public ActionResult AuditList() {
        return View();
    }

    public ActionResult CorrectiveActionList() {
        return View();
    }

    public ActionResult ECN_TECN(string viewOption) {
        ViewBag.ViewOption = viewOption;
        return View();
    }

    public ActionResult ChangeControlList() {
        return View();
    }

    public ActionResult GetTaskList([DataSourceRequest] DataSourceRequest request, string tabName) {
        try {
            ViewBag.ActiveTabName = tabName;
            List<IssuesViewModel> data = ldDMO.GetTaskList((int)Session[GlobalVars.SESSION_USERID]).Distinct().ToList();
            return Json(data.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
        } catch (Exception ex) {
            // TODO record the error
            throw ex;
        }
    }

    public ActionResult GetMyOpenActionItems([DataSourceRequest] DataSourceRequest request, string tabName) {
        try {
            ViewBag.ActiveTabName = tabName;
            List<OpenActionItemViewModel> data = ldDMO.GetMyOpenActionItems((int)Session[GlobalVars.SESSION_USERID]).Distinct().ToList();
            return Json(data.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
        } catch (Exception ex) {
            // TODO record the error
            throw ex;
        }
    }

    public ActionResult GetDocuments([DataSourceRequest] DataSourceRequest request, string tabName) {
        ViewBag.ActiveTabName = tabName;
        IEnumerable<IssuesViewModel> data = ldDMO.GetDocuments();
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult GetWorkRequests([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<IssuesViewModel> data = ldDMO.GetWorkRequests();
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult GetChangeControlList([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<ChangeControlList> data = ldDMO.GetChangeControls(int.Parse(Session[GlobalVars.SESSION_USERID].ToString()));
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult GetAuditList([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<AuditList> data = ldDMO.GetAuditList(int.Parse(Session[GlobalVars.SESSION_USERID].ToString()));
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult GetCorrectiveActionList([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<CorrectiveAction> data = ldDMO.GetCorrectiveActionList(int.Parse(Session[GlobalVars.SESSION_USERID].ToString()));
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult GetMRBList([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<IssuesViewModel> data = ldDMO.GetMRBList(int.Parse(Session[GlobalVars.SESSION_USERID].ToString()));
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult GetLotDispositionList([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<IssuesViewModel> data = ldDMO.GetLotDispositionList(int.Parse(Session[GlobalVars.SESSION_USERID].ToString()));
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult GetECNList([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<IssuesViewModel> data = ldDMO.GetECNList(int.Parse(Session[GlobalVars.SESSION_USERID].ToString()));
        return Json(data.ToDataSourceResult(request));
    }
    public ActionResult GetTrainingList([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<Training> data = trainingDMO.GetAllTrainings();
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult MyECNsTECNs(string dataType) {
        ViewBag.ActiveTabName = dataType;
        return View();
    }

    public ActionResult GetECN_TECNsPendingApproval([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<IssuesViewModel> data = ecnDMO.GetECN_TECNPendingApprovals(int.Parse(Session[GlobalVars.SESSION_USERID].ToString()));
        ViewBag.ViewOption = "Pending Approvals";
        Session[GlobalVars.ECN_VIEW_OPTION] = ViewBag.ViewOption;
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult GetMyExpiredTECNs([DataSourceRequest] DataSourceRequest request) {

        IEnumerable<IssuesViewModel> data = ecnDMO.GetMyExpiredTECNs(int.Parse(Session[GlobalVars.SESSION_USERID].ToString()), 7);
        ViewBag.ViewOption = "Expired TECNs";
        Session[GlobalVars.ECN_VIEW_OPTION] = ViewBag.ViewOption;
        return Json(data.ToDataSourceResult(request));
    }
    public ActionResult GetAllTECNs([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<IssuesViewModel> data = ecnDMO.GetAllTECNs();
        ViewBag.ViewOption = "All TECNs";
        Session[GlobalVars.ECN_VIEW_OPTION] = ViewBag.ViewOption;
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult GetMyConvertedTECNsToECNs([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<IssuesViewModel> data = ecnDMO.GetMyConvertedTECNsToECNs(int.Parse(Session[GlobalVars.SESSION_USERID].ToString()), 7);
        ViewBag.ViewOption = "Converted TECNs";
        Session[GlobalVars.ECN_VIEW_OPTION] = ViewBag.ViewOption;
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult GetMyExpiringTECNs([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<IssuesViewModel> data = ecnDMO.GetMyExpiringTECNs(int.Parse(Session[GlobalVars.SESSION_USERID].ToString()), 7);
        ViewBag.ViewOption = "Expiring TECNs";
        Session[GlobalVars.ECN_VIEW_OPTION] = ViewBag.ViewOption;
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult GetLotList([DataSourceRequest] DataSourceRequest request, int workRequestID) {
        LotTravelerDMO LotTravDMO = new LotTravelerDMO();
        return Json(LotTravDMO.GetLotListBasedOnSWRNumber(workRequestID).ToDataSourceResult(request));
    }

    /// <returns></returns>

    public ActionResult SetOOOStatus(int delegatedTo, DateTime startDate, DateTime endDate, string tab) {
        if (Session[GlobalVars.SESSION_USERID] != null) {
            int returnValue = MiscDMO.EnableOOOStatus(int.Parse(Session[GlobalVars.SESSION_USERID].ToString()), delegatedTo, startDate, endDate);
            if (returnValue == 3) // the delegator is already a delegator to someone else
            {
                return Content("3");
            }
            if (startDate <= DateTime.Today)
                Session[GlobalVars.OOO] = true;

            NotifyDelegation(delegatedTo, startDate, endDate);
        }

        return Content("");
    }

    public void ExpireOOOStatus(string tab) {
        if (Session[GlobalVars.SESSION_USERID] != null) {
            MiscDMO.ExpireOOOStatus(int.Parse(Session[GlobalVars.SESSION_USERID].ToString()));
            Session[GlobalVars.OOO] = false;
        }
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult DeleteItem([DataSourceRequest] DataSourceRequest request, IssuesViewModel issue) {
        GlobalVars.DocumentType dType;
        Enum.TryParse(issue.DocumentType, out dType);
        if (dType == GlobalVars.DocumentType.MRB)
            mrbDMO.DeleteMRB(issue.IssueID);
        else if (dType == GlobalVars.DocumentType.LotDisposition)
            ldDMO.DeleteLotDisposition(issue.IssueID);
        else if (dType == GlobalVars.DocumentType.ECN)
            ecnDMO.DeleteDocument(issue.IssueID, int.Parse(Session[GlobalVars.SESSION_USERID].ToString()), "ECN");
        else if (dType == GlobalVars.DocumentType.CorrectiveAction)
            ldDMO.DeleteCADocument(issue.IssueID, int.Parse(Session[GlobalVars.SESSION_USERID].ToString()), "Corrective Action");

        return Json(new[] { issue }.ToDataSourceResult(request, ModelState));
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult DeleteCAItem([DataSourceRequest] DataSourceRequest request, CorrectiveAction ca) {
        ldDMO.DeleteCADocument(ca.CANo, int.Parse(Session[GlobalVars.SESSION_USERID].ToString()), "Corrective Action");

        return Json(new[] { ca }.ToDataSourceResult(request, ModelState));
    }

    public ActionResult About() {
        ViewBag.Message = "Your application description page.";

        return View();
    }

    public ActionResult Contact() {
        ViewBag.Message = "Your contact page.";

        return View();
    }

    #region testing purpose
    public ActionResult Edit() {
        return View(DemoHelper.Instance.ListOfModels[0]);
    }

    [HttpPost]
    public ActionResult Edit(TestModel editTest) {
        DemoHelper.Instance.ListOfModels[0] = editTest;
        return RedirectToAction("Index");
    }

    public static void Test() {
        string[] colorStrings = { "0", "2", "8", "blue", "Blue", "Yellow", "Red, Green" };
        foreach (string colorString in colorStrings) {
            GlobalVars.Colors colorValue;
            if (Enum.TryParse(colorString, true, out colorValue))
                if (Enum.IsDefined(typeof(GlobalVars.Colors), colorValue) | colorValue.ToString().Contains(","))
                    Console.WriteLine("Converted '{0}' to {1}.", colorString, colorValue.ToString());
                else
                    Console.WriteLine("{0} is not an underlying value of the Colors enumeration.", colorString);
            else
                Console.WriteLine("{0} is not a member of the Colors enumeration.", colorString);
        }
    }

    #endregion

    public void DelegateDocumentApproval(int issueID, int delegateTo, string ecnTypeString, string title) {
        var email = "";
        int delegateFrom = (int)Session[GlobalVars.SESSION_USERID];
        try {
            email = wfDMO.DelegateDocumentApproval(issueID, delegateFrom, delegateTo);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = ecnTypeString, OperationType = "Delegation", Comments = "Delegated from - " + delegateFrom + " to " + delegateTo });
        } catch (Exception e) {
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "Issue=" + issueID.ToString() + " " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n DelegateApproval\r\n" + e.Message.ToString(), System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = " + ecnTypeString + ", OperationType = "Error", Comments = "DelegateApproval - " + exceptionString });
            throw new Exception(e.Message);
        }
        HomeHelper.DelegateDocumentApproval(_AppSettings, issueID, ecnTypeString, title, email);
        try {
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = ecnTypeString, OperationType = "Email", Comments = "Delegated to Approver: " + email });
        } catch { }
    }

    public JsonResult GetAllUsersList() {

        UserAccountDMO userDMO = new UserAccountDMO();
        IEnumerable<LoginModel> userlist = userDMO.GetAllUsers();
        return Json(userlist, JsonRequestBehavior.AllowGet);
    }

    public ActionResult SaveAllDocumentsFilter(string data) {
        Session["AllDocumentsFilterData"] = data;
        return new EmptyResult();
    }

    public ActionResult LoadAllDocumentsFilter() {
        return Json(Session["AllDocumentsFilterData"], JsonRequestBehavior.AllowGet);
    }

    public ActionResult SaveSWRFilter(string data) {
        Session["SWRFilterData"] = data;
        return new EmptyResult();
    }

    public ActionResult LoadSWRFilter() {
        return Json(Session["SWRFilterData"], JsonRequestBehavior.AllowGet);
    }

    public ActionResult SavePCRBFilter(string data) {
        Session["PCRBFilterData"] = data;
        return new EmptyResult();
    }

    public ActionResult LoadPCRBFilter() {
        return Json(Session["PCRBFilterData"], JsonRequestBehavior.AllowGet);
    }

    public ActionResult PartsRequestList() {
        ViewBag.CanDeletePR = Session[GlobalVars.CAN_CREATE_PARTS_REQUEST];
        return View();
    }

    public ActionResult GetPartsRequestList([DataSourceRequest] DataSourceRequest request) {
        IEnumerable<PartsRequestList> data = prDMO.GetPartsRequestList();
        return Json(data.ToDataSourceResult(request));
    }

    public ActionResult GetMyPartsRequestsList([DataSourceRequest] DataSourceRequest request, string tabName) {
        try {
            ViewBag.ActiveTabName = tabName;
            var data = prDMO.GetMyPartsRequests((int)Session[GlobalVars.SESSION_USERID]);
            return Json(data.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
        } catch (Exception ex) {
            // TODO record the error
            throw ex;
        }
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult DeletePR([DataSourceRequest] DataSourceRequest request, MyPartsRequestList pr) {
        try {
            if (Convert.ToBoolean(Session[GlobalVars.CAN_CREATE_PARTS_REQUEST]) == false)
                throw new Exception("Permission denied");

            prDMO.DeleteDocument(pr.PRNumber, (int)Session[GlobalVars.SESSION_USERID]);
            return Json(new[] { pr }.ToDataSourceResult(request, ModelState));
        } catch (Exception ex) {
            return new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest, ex.Message);
        }
    }

    public void NotifyDelegation(int delegatedUser, DateTime startDate, DateTime endDate) {
        LoginModel delegateFrom = originalUserDMO.GetUserByID((int)Session[GlobalVars.SESSION_USERID]);
        LoginModel delegateTo = originalUserDMO.GetUserByID(delegatedUser);
        List<string> emailList = new List<string>();
        emailList.Add(delegateFrom.Email);
        emailList.Add(delegateTo.Email);
        HomeHelper.NotifyDelegation(_AppSettings, startDate, endDate, delegateFrom, delegateTo, emailList);
        try {
        } catch { }
    }

    public bool ProcessOoO() {

        try {
            UserAccountDMO userDMO = new UserAccountDMO();
            userDMO.ProcessOoO();
            return true;
        } catch {
            return false;
        }
    }
    public bool ExpireOoO() {
        try {
            UserAccountDMO userDMO = new UserAccountDMO();
            userDMO.ExpireOoO();
            return true;
        } catch {
            return false;
        }
    }
    public bool ApprovalsReminderNotifications() {
        try {
            // Get list of approvals
            List<ApproveListModel> approveList = miscDMO.GetApprovalReminderList();

            foreach (var item in approveList) {
                try {
                    NotifyApprover(item.AssignedEmail, item.Title, item.IssueID, item.DocType);
                } catch (Exception e) {
                    EventLogDMO.Add(new WinEventLog() { IssueID = item.ApprovalKey, UserID = "SYSTEM", DocumentType = "Approval Reminders", OperationType = "Email", Comments = e.Message });
                }
                // We want to update the last notification anyway so we don't continue trying on something that may be failing.
                miscDMO.UpdateApprovalNotifyDate(item.ApprovalKey);
            }
            // List<ApproveListModel> approveList = miscDMO.
            return true;
        } catch {
            return false;
        }
    }
    public void NotifyApprover(string toEmail, string title, int issueId, string docType) {
        try {
            HomeHelper.NotifyApprover(_AppSettings, toEmail, title, issueId, docType);

            try {
                EventLogDMO.Add(new WinEventLog() { IssueID = issueId, UserID = @User.Identity.Name, DocumentType = docType, OperationType = "Email", Comments = "Approval reminders" });
            } catch { }

        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            EventLogDMO.Add(new WinEventLog() { IssueID = issueId, UserID = @User.Identity.Name, DocumentType = docType, OperationType = "Email", Comments = "Approval reminders" });
            throw e;
        }
    }

}