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 Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;

namespace Fab2ApprovalSystem.Controllers;

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

    AuditDMO auditDMO = new AuditDMO(GlobalVars.AppSettings);
    CorrectiveActionDMO caDMO = new CorrectiveActionDMO();
    private readonly AppSettings _AppSettings = GlobalVars.AppSettings;

    // GET: Audit
    public ActionResult Index() {
        return View();
    }

    public ActionResult Create() {
        Audit audit = new Audit();
        try {
            // TODO: Add insert logic here

            audit.OriginatorID = (int)Session[GlobalVars.SESSION_USERID];
            auditDMO.InsertAudit(audit);
            return RedirectToAction("Edit", new { issueID = audit.AuditNo });
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "Issue=" + audit.AuditNo.ToString() + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n SubmitDocument - Audit\r\n" + audit.AuditNo.ToString() + "\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = audit.AuditNo, UserID = @User.Identity.Name, DocumentType = "Audit", OperationType = "Error", Comments = "SubmitDocument - " + exceptionString });
            throw new Exception(e.Message);
        }
    }

    public ActionResult Edit(int issueID) {
        int isITARCompliant = 1;
        Audit audit = new Audit();

        try {
            bool isAdmin = (bool)Session[GlobalVars.IS_ADMIN];
            int userId = (int)Session[GlobalVars.SESSION_USERID];
            AuditEdit auditEdit = auditDMO.GetAuditEdit(issueID, audit, isAdmin, userId);
            if (auditEdit.RedirectToAction)
                return RedirectToAction("ReadOnlyAudit", new { auditNo = audit.AuditNo });
            ViewBag.AuditAreaList = auditEdit.AuditAreaList;
            ViewBag.AuditeeNames = auditEdit.AuditeeNames;
            ViewBag.AuditFindingCategoryList = auditEdit.AuditFindingCategoryList;
            ViewBag.AuditorList = auditEdit.AuditorList;
            ViewBag.AuditTypeList = auditEdit.AuditTypeList;
            ViewBag.CANoList = auditEdit.CANoList;
            ViewBag.Is8DQA = auditEdit.Is8DQA;
            ViewBag.IsAdmin = auditEdit.IsAdmin;
            ViewBag.IsSubmitter = auditEdit.IsSubmitter;
            ViewBag.MesaUsers = auditEdit.MesaUsers;
            ViewBag.UserList = auditEdit.UserList;
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "Issue=" + audit.AuditNo.ToString() + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n Edit - Audit\r\n" + audit.AuditNo.ToString() + "\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = audit.AuditNo, UserID = @User.Identity.Name, DocumentType = "Audit", OperationType = "Error", Comments = "Edit - " + exceptionString });
            throw new Exception(e.Message);
        }

        return View(audit);
    }

    [HttpPost]
    public ActionResult Edit(Audit model) {
        try {
            var data = model;
            auditDMO.UpdateAudit(model, (int)Session[GlobalVars.SESSION_USERID]);
        } catch (Exception ex) {
            return Content(ex.Message);
        }

        return Content("Successfully Saved");
    }

    public ActionResult CheckCAStatus(int auditNo) {
        int dataCount = -1;
        try {
            dataCount = auditDMO.GetOpenCACountByAuditNo(auditNo);
        } catch (Exception ex) {
            throw;
        }

        return Content(dataCount.ToString());
    }

    public ActionResult ReadOnlyAudit(int auditNo) {
        Audit audit = new Audit();
        audit = auditDMO.GetAuditItemReadOnly(auditNo, (int)Session[GlobalVars.SESSION_USERID]);

        ViewBag.AuditTypeList = auditDMO.GetAuditTypeList();
        ViewBag.AuditorList = auditDMO.GetAuditorList();
        ViewBag.AuditAreaList = auditDMO.GetAuditAreaList();
        ViewBag.AuditFindingCategoryList = auditDMO.GetAuditFindingCategories();

        return View(audit);
    }

    public ActionResult AuditReportAttachSave(IEnumerable<HttpPostedFileBase> AuditReportFiles, int auditNo) {
        try {
            // The Name of the Upload component is "files"
            if (AuditReportFiles != null) {
                int userId = (int)Session[GlobalVars.SESSION_USERID];
                foreach (var file in AuditReportFiles) {
                    AuditHelper.AuditReportAttachSave(_AppSettings, auditDMO, auditNo, userId, file.FileName, file.InputStream);
                }
            }
        } catch {
            throw;
        }

        return Content("");
    }

    public ActionResult AuditReportAttachment_Read([DataSourceRequest] DataSourceRequest request, int auditNo) {

        return Json(auditDMO.GetAuditReportAttachments(auditNo).ToDataSourceResult(request));
    }

    [HttpPost]
    public void DeleteAuditReportAttachment(int attachID) {
        auditDMO.DeleteAuditReportAttachment(attachID);
    }

    public FileResult DownloadAuditReportAttachment(string fileGuid, int auditNo) {
        try {
            string fileName, sDocument;
            List<string> results = AuditHelper.GetFileNameAndDocument(_AppSettings, auditDMO, fileGuid, auditNo);
            fileName = results[0];
            sDocument = results[1];
            if (string.IsNullOrEmpty(sDocument)) {
                // Ensure that we are serving file only inside the Fab2ApprovalAttachments folder
                // and block requests outside like "../web.config"
                throw new HttpException(403, "Forbidden");
            }

            if (!System.IO.File.Exists(sDocument)) {
                return null;
            }

            return File(sDocument, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
        } catch {
            // TODO - proces the error
            throw;
        }
    }

    public ActionResult GetAuditFindingsList([DataSourceRequest] DataSourceRequest request, int auditNo) {
        return Json(auditDMO.GetAuditFindingsList(auditNo).ToDataSourceResult(request));
    }

    public ActionResult InsertAuditFindingsItem(AuditFindings data) {
        if ((data.FindingType == "Major" || data.FindingType == "Minor") && data.CANo == 0) {
            throw new ArgumentException("You must select add a CA for a Major or Minor finding.");
        } else {
            int userId = (int)Session[GlobalVars.SESSION_USERID];
            Audit audit = auditDMO.InsertAndGetAudit(caDMO, data, userId);

            return Json(audit, JsonRequestBehavior.AllowGet);
        }
    }

    public ActionResult UpdateAuditFindingsItem(AuditFindings data) {
        if ((data.FindingType == "Major" || data.FindingType == "Minor") && data.CANo == 0) {
            throw new ArgumentException("You must select add a CA for a Major or Minor finding.");
        } else {
            int userId = (int)Session[GlobalVars.SESSION_USERID];
            Audit audit = auditDMO.UpdateAndGetAudit(caDMO, data, userId);

            return Json(audit, JsonRequestBehavior.AllowGet);
        }
    }

    public ActionResult DeleteAuditFindingsItem(int auditFindingsID) {
        int userId = (int)Session[GlobalVars.SESSION_USERID];
        Audit audit = auditDMO.DeleteAndGetAudit(auditFindingsID, userId);
        return Json(audit, JsonRequestBehavior.AllowGet);
    }

    public void ReleaseLockOnDocument(int issueID) {
        try {
            auditDMO.ReleaseLockOnDocument((int)Session[GlobalVars.SESSION_USERID], issueID);
        } catch (Exception e) {
            try {
                Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n ReleaseLockOnDocument CA\r\n" + issueID.ToString() + "\r\n" + e.Message, System.Diagnostics.EventLogEntryType.Error);
            } catch { }
            auditDMO.ReleaseLockOnDocument(-1, issueID);
        }
    }

    // CA Findings ======================================================================================================================

    public ActionResult InsertCAFindingsItem(CAFindings data) {
        auditDMO.InsertCAFindings(data);
        if (data.ResponsibilityOwnerID != null) {
            // send an email notification
            NotifyActionItemOwner(data.AuditNo, data.ECD, data.ResponsibilityOwnerID);
        }

        return Content("");
    }

    public ActionResult UpdateCAFindingsItem(CAFindings data) {
        auditDMO.UpdateCAFindings(data);
        if (data.ResponsibilityOwnerID != data.CurrentResponsibilityOwnerID) {
            NotifyActionItemOwner(data.AuditNo, data.ECD, data.ResponsibilityOwnerID);
        }

        return Content("");
    }

    public ActionResult GetCAFindingsList([DataSourceRequest] DataSourceRequest request, int auditNo) {
        return Json(auditDMO.GetCAFindingsList(auditNo).ToDataSourceResult(request));
    }

    public ActionResult GetCAFindingsItemAttachments([DataSourceRequest] DataSourceRequest request, int caFindingsID) {
        return Json(auditDMO.GetCAFindingsItemAttachments(caFindingsID).ToDataSourceResult(request));
    }

    public ActionResult GetCAFindingsItem(int caFindingsID) {
        var model = new CAFindings();
        model = auditDMO.GetCAFindingsItem(caFindingsID);

        return PartialView("_CAFindingsAttachment", model);
    }

    [HttpPost]
    public void DeleteCAFindingsItem(int caFindingsID) {
        auditDMO.DeleteCAFindingsItem(caFindingsID);
    }

    public ActionResult SaveCAFindings_Attachemnt(IEnumerable<HttpPostedFileBase> CAFindings_Attachemnt, int caFindingsID, int auditNo) {
        try {
            // The Name of the Upload component is "files"
            if (CAFindings_Attachemnt != null) {
                int userId = (int)Session[GlobalVars.SESSION_USERID];
                foreach (var file in CAFindings_Attachemnt) {
                    AuditHelper.SaveAndInsert(_AppSettings, auditDMO, caFindingsID, auditNo, userId, file.FileName, file.InputStream);
                }
            }
        } catch {
            throw;
        }

        return Content("");
    }

    public void NotifyActionItemOwner(int issueID, DateTime? dueDate, int? responsibleOwnerID) {
        try {
            string email = auditDMO.NotifyActionItemOwner(issueID, dueDate, responsibleOwnerID, _AppSettings.EmailTemplatesPath);

            try {
                EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Corrective Action", OperationType = "Email", Comments = "Task Assigned for 5S/CA Findings" + ":" + email });
            } catch { }
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }

            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "Issue=" + issueID.ToString() + " 5s/CAFindings:" + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n 5s/CAFindings - NotifyActionItemOwner\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Corrective Action", OperationType = "Error", Comments = "5s/CAFindings Notification - " + exceptionString });
        }
    }

    public ActionResult IsCAAssignedToAudit(int caNo, int auditNo) {
        return Content(auditDMO.IsCAAssignedToAudit(caNo, auditNo).ToString());
    }

}