using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Web;
using System.Web.Mvc;

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

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

namespace Fab2ApprovalSystem.Controllers;

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

    LotDispositionDMO ldDMO = new LotDispositionDMO();
    WorkflowDMO wfDMO = new WorkflowDMO();
    private readonly AppSettings _AppSettings = GlobalVars.AppSettings;

    // GET: /LotDisposition/Create
    public ActionResult Create() {
        LotDisposition lotDispo = new LotDisposition();
        try {
            // insert a records to get the issueID

            lotDispo.OriginatorID = (int)Session[GlobalVars.SESSION_USERID];
            ldDMO.InsertLotDisposition(lotDispo);
            return RedirectToAction("Edit", new { issueID = lotDispo.IssueID.ToString() });
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\nCreat Lot Disposition\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = lotDispo.IssueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = exceptionString });
            return View("Error");
        }
    }

    public JsonResult AddLot(Lot lot) {
        Lot l = lot;
        MRB_DMO mrbDMO = new MRB_DMO(_AppSettings);
        IssueWithExistingLotsViewModel issueWEL = new IssueWithExistingLotsViewModel();
        try {

            lot.LotStatusOption.LotStatusOptionID = l.LotStatusOptionID;
            lot.LotStatusOption.LotStatusOption = l.LotStatusOptionName;
            ldDMO.InsertLot(lot, false);
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "IssueID=" + lot.IssueID.ToString() + "  " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n Add Lot Disposition\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = l.IssueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = exceptionString });
            throw new Exception(e.Message);
        }
        return Json(l, JsonRequestBehavior.AllowGet);
    }

    public JsonResult AddLots(string lotNumbers, int issueID) {
        MRB_DMO mrbDMO = new MRB_DMO(_AppSettings);
        bool existingLotUpdated;
        IssueWithExistingLotsViewModel issueWEL = new IssueWithExistingLotsViewModel();
        try {
            if (lotNumbers.Length > 0) {
                string[] tempLots = lotNumbers.Split(new char[] { '~' });
                foreach (string lotNumber in tempLots) {
                    Lot l = new Lot();
                    l.LotNumber = lotNumber;
                    l.IssueID = issueID;
                    l.LotStatusOption.LotStatusOptionID = (int)GlobalVars.LotStatusOption.NotAvailable;
                    ldDMO.InsertLot(l, true);
                    if (l.OpenIssueWithExistingLots != 0) {
                        issueWEL.LotList += l.LotNumber + "~";
                        issueWEL.IssuesList += l.OpenIssueWithExistingLots + "~";
                    }

                }

            }

        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "IssueID=" + issueID.ToString() + "  " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n AddLots Disposition\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = exceptionString });
            throw new Exception(e.Message);
        }

        return Json(issueWEL, JsonRequestBehavior.AllowGet);
    }

    // GET: /LotDisposition/Edit/5
    public ActionResult Edit(int issueID) {
        int isITARCompliant = 1;
        try {
            LotDisposition lotDispo = new LotDisposition();
            lotDispo = ldDMO.GetLotDispositionItemForRead(issueID, out isITARCompliant, (int)Session[GlobalVars.SESSION_USERID]);

            if (isITARCompliant == 0) // not ITAR Compliant
            {
                return View("UnAuthorizedAccess");
            } else {
                if (lotDispo.CloseDate != null) {
                    return RedirectToAction("ReadOnly", new { issueID = issueID });
                }
                if (lotDispo.CurrentStep == 1) {
                    List<ApproversListViewModel> userList = MiscDMO.GetPendingApproversListByDocument(issueID, lotDispo.CurrentStep, (int)GlobalVars.DocumentType.LotDisposition);
                    ApproversListViewModel approver = userList.Find(delegate (ApproversListViewModel al) { return al.UserID == (int)Session[GlobalVars.SESSION_USERID]; });
                    if (approver == null)
                        ViewBag.IsApprover = "false";
                    else
                        ViewBag.IsApprover = "true";

                    if (approver == null && (!(bool)Session[GlobalVars.IS_ADMIN]) && (int)Session[GlobalVars.SESSION_USERID] != lotDispo.OriginatorID) {
                        return RedirectToAction("ReadOnly", new { issueID = issueID });
                    } else {
                        if ((ViewBag.IsApprover == "true" || (bool)Session[GlobalVars.IS_ADMIN])
                            || (int)Session[GlobalVars.SESSION_USERID] == lotDispo.OriginatorID) {
                            lotDispo = ldDMO.GetLotDispositionItem(issueID, out isITARCompliant, (int)Session[GlobalVars.SESSION_USERID]);

                            if (lotDispo.RecordLockIndicator && lotDispo.RecordLockedBy == (int)Session[GlobalVars.SESSION_USERID]) {
                                PopulateLotStatusOptions();
                                ViewBag.OriginatorList = ldDMO.GetUserList();
                                ViewBag.deps = ldDMO.GetDepartments();
                                ViewBag.ResponsibilityList = ldDMO.GetResponsibilityList();
                                ViewBag.ResponsibilityIssueList = ldDMO.GetResponsibilityIssueList(lotDispo.ResponsibilityID);

                                return View(lotDispo);
                            } else {
                                return RedirectToAction("ReadOnly", new { issueID = issueID });
                            }
                        } else {
                            return RedirectToAction("ReadOnly", new { issueID = issueID });
                        }
                    }
                } else if (lotDispo.CurrentStep > 1) {
                    List<ApproversListViewModel> userList = MiscDMO.GetPendingApproversListByDocument(issueID, lotDispo.CurrentStep, (int)GlobalVars.DocumentType.LotDisposition);

                    ApproversListViewModel approver = userList.Find(delegate (ApproversListViewModel al) { return al.UserID == (int)Session[GlobalVars.SESSION_USERID]; });
                    if (approver == null) {
                        ViewBag.IsApprover = "false";

                    } else {
                        ViewBag.IsApprover = "true";

                    }

                    if (approver == null && (!(bool)Session[GlobalVars.IS_ADMIN]) && (int)Session[GlobalVars.SESSION_USERID] != lotDispo.OriginatorID) {
                        return RedirectToAction("ReadOnly", new { issueID = issueID });
                    } else {

                        if ((ViewBag.IsApprover == "true" || (bool)Session[GlobalVars.IS_ADMIN])
                           || (int)Session[GlobalVars.SESSION_USERID] == lotDispo.OriginatorID) {
                            return RedirectToAction("EditStep", new { issueID = issueID });

                        } else {
                            return RedirectToAction("ReadOnly", new { issueID = issueID });
                        }

                    }

                } else {
                    // TODO
                    // Check the recordlock indicator
                    if ((lotDispo.RecordLockIndicator && lotDispo.RecordLockedBy != (int)Session[GlobalVars.SESSION_USERID]) || (ViewBag.IsApprover == "false")) {
                        return RedirectToAction("ReadOnly", new { issueID = issueID });
                    } else {
                        lotDispo = ldDMO.GetLotDispositionItem(issueID, out isITARCompliant, (int)Session[GlobalVars.SESSION_USERID]);
                        PopulateLotStatusOptions();
                        ViewBag.OriginatorList = ldDMO.GetUserList();
                        ViewBag.deps = ldDMO.GetDepartments();
                        ViewBag.ResponsibilityList = ldDMO.GetResponsibilityList();
                        ViewBag.ResponsibilityIssueList = ldDMO.GetResponsibilityIssueList(lotDispo.ResponsibilityID);

                        return View(lotDispo);
                    }
                }
            }
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\nEdit Lot Disposition\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = exceptionString });
            return View("Error");
        }
    }

    // POST: /LotDisposition/Edit/5

    [HttpPost]
    public void Edit(LotDisposition lotDispo) {
        try {
            ldDMO.UpdateLotDisposition(lotDispo);
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "IssueID=" + lotDispo.IssueID.ToString() + "  " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n UpdatEdit Disposition\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = lotDispo.IssueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = exceptionString });
            throw new Exception(e.Message);
        }
    }

    public ActionResult ReadOnly(int issueID) {
        int isITARCompliant = 1;
        try {
            LotDisposition lotDispo = new LotDisposition();
            lotDispo = ldDMO.GetLotDispositionItemForRead(issueID, out isITARCompliant, (int)Session[GlobalVars.SESSION_USERID]);

            PopulateLotStatusOptions();
            ViewBag.OriginatorList = ldDMO.GetUserList();
            ViewBag.deps = ldDMO.GetDepartments();
            ViewBag.ResponsibilityList = ldDMO.GetResponsibilityList();
            ViewBag.ResponsibilityIssueList = ldDMO.GetResponsibilityIssueList(lotDispo.ResponsibilityID);

            return View(lotDispo);
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "IssueID=" + issueID.ToString() + "  " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n ReadOnly Disposition\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = exceptionString });
            throw new Exception(e.Message);
        }
    }

    public ActionResult EditStep(int issueID) {
        int isITARCompliant = 1;
        try {

            LotDisposition lotDispo = new LotDisposition();
            lotDispo = ldDMO.GetLotDispositionItemForRead(issueID, out isITARCompliant, (int)Session[GlobalVars.SESSION_USERID]);
            List<ApproversListViewModel> userList = MiscDMO.GetPendingApproversListByDocument(issueID, lotDispo.CurrentStep, (int)GlobalVars.DocumentType.LotDisposition);
            ApproversListViewModel appUser = userList.Find(delegate (ApproversListViewModel al) { return al.UserID == (int)Session[GlobalVars.SESSION_USERID]; });
            if (appUser == null)
                ViewBag.IsApprover = "false";
            else
                ViewBag.IsApprover = "true";

            // Check the recordlock indicator

            if ((ViewBag.IsApprover == "true" || (bool)Session[GlobalVars.IS_ADMIN])) {
                lotDispo = ldDMO.GetLotDispositionItem(issueID, out isITARCompliant, (int)Session[GlobalVars.SESSION_USERID]);

                if (lotDispo.RecordLockIndicator && lotDispo.RecordLockedBy == (int)Session[GlobalVars.SESSION_USERID]) {
                    PopulateLotStatusOptions();
                    ViewBag.OriginatorList = ldDMO.GetUserList();
                    ViewBag.deps = ldDMO.GetDepartments();
                    ViewBag.ResponsibilityList = ldDMO.GetResponsibilityList();
                    ViewBag.ResponsibilityIssueList = ldDMO.GetResponsibilityIssueList(lotDispo.ResponsibilityID);

                    return View(lotDispo);
                } else {
                    return RedirectToAction("ReadOnly", new { issueID = issueID });
                }
            } else {
                return RedirectToAction("ReadOnly", new { issueID = issueID });
            }

        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "IssueID=" + issueID.ToString() + "  " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n EditStep Disposition\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = exceptionString });
            throw new Exception(e.Message);
        }
    }

    // GET: /LotDisposition/Delete/5
    public ActionResult Delete(int id) {
        return View();
    }

    public JsonResult GetResponsibilityIssue(int responsibilityID) {
        List<ResponsibilityIssue> respIssue = ldDMO.GetResponsibilityIssueList(responsibilityID);

        var data = respIssue.Select(s => new SelectListItem { Value = s.ResponsibilityIssueID.ToString(), Text = s.Issue });
        return Json(data, JsonRequestBehavior.AllowGet);
    }

    public JsonResult GetDepartments([DataSourceRequest] DataSourceRequest request) {
        var departments = ldDMO.GetDepartments();
        return Json(departments, JsonRequestBehavior.AllowGet);
    }

    public void PopulateLotStatusOptions() {
        var lotStatusOptions = ldDMO.GetLotStatusOptions();
        ViewData["LotStatusOptions"] = lotStatusOptions;
    }

    public ActionResult EditingCustom_Read([DataSourceRequest] DataSourceRequest request, int issueID) {
        return Json(ldDMO.GetLotDispositionLots(issueID).ToDataSourceResult(request));
    }

    /// <summary>
    /// Updates the lot tables
    /// </summary>
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult EditingCustom_Update([DataSourceRequest] DataSourceRequest request, Lot lot) {

        if (lot != null && ModelState.IsValid) {
            ldDMO.UpdateLotDispoLot(lot);
        }

        lot.LotStatusOptionID = lot.LotStatusOption.LotStatusOptionID;
        return Json(new[] { lot }.ToDataSourceResult(request, ModelState));
    }

    /// <summary>
    /// Deletes record from the lot table
    /// </summary>

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult EditingCustom_Destroy([DataSourceRequest] DataSourceRequest request, Lot lot) {
        try {
            if (lot != null && ModelState.IsValid) {
                ldDMO.DeleteLotDispoLot(lot.LotID);

            }
        } catch (Exception ex) {
            // TODO
            throw new Exception(ex.Message);
        }

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

    // REGION ATTACHMENT

    public ActionResult Attachment_Read([DataSourceRequest] DataSourceRequest request, int issueID) {
        return Json(ldDMO.GetLotDispoAttachments(issueID).ToDataSourceResult(request));
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Attachment_Destroy([DataSourceRequest] DataSourceRequest request, Attachment attachment) {
        try {
            if (attachment != null && ModelState.IsValid) {
                ldDMO.DeleteLotDispoAttachment(attachment.AttachmentID);

            }
        } catch (Exception e) {
        }

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

    [HttpPost]
    public void DeleteAttachment(int attachmentID, string fileName) {
        try {
            if (ModelState.IsValid) {
                ldDMO.DeleteLotDispoAttachment(attachmentID);
                var physicalPath = System.IO.Path.Combine(_AppSettings.AttachmentFolder + "LotDisposition", fileName);

                System.IO.FileInfo f = new System.IO.FileInfo(physicalPath);

                if (f.Exists)
                    f.Delete();

            }
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "AttachmentID=" + attachmentID.ToString() + "  " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n AttachmentID Disposition\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = 999, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "AttachmentID Disposition " + exceptionString });
            throw new Exception(e.Message);
        }
    }

    public JsonResult GetLotDispoAttachments(int issueID) {
        var model = ldDMO.GetLotDispoAttachments(issueID);
        return Json(model, JsonRequestBehavior.AllowGet);
    }

    public ActionResult AttachSave(IEnumerable<HttpPostedFileBase> files, int issueID) {
        // The Name of the Upload component is "files"
        if (files != null) {
            int userId = (int)Session[GlobalVars.SESSION_USERID];
            foreach (var file in files) {
                LotDispositionHelper.AttachSave(_AppSettings, ldDMO, issueID, userId, file.FileName, file.InputStream);
            }
        }

        return Content("");
    }

    public JsonResult SearchLots(string searchText, string searchBy) {
        List<String> lotlist = MiscDMO.SearchLots(searchText, searchBy).Select(x => x.LotNumber).ToList<String>();

        return Json(lotlist, JsonRequestBehavior.AllowGet);
    }

    public void DeleteAllLots(int issueID) {
        // trap the error on then client side
        ldDMO.DeleteAllLotDispoLot(issueID);
    }

    [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
    public ActionResult LotStatusDetail(int issueID, string lotNumber, bool readonlyView, string lotLocation = "") {
        ViewBag.LotLocation = lotLocation;
        var model = new ScrapLot();
        var data = ldDMO.GetLotStausDetail(issueID, lotNumber);
        if (data != null)
            model = data;

        model.IssueID = issueID;
        model.LotNo = lotNumber;

        if (lotLocation.Equals("QDB", StringComparison.OrdinalIgnoreCase) ||
            lotLocation.Equals("EDB", StringComparison.OrdinalIgnoreCase)) {
            model.WaferCount = 50;
        }

        if (readonlyView)
            return PartialView("_ScrapReleaseReadOnly", model);
        else
            return PartialView("_ScrapRelease", model);
    }

    public void UpdateLotScrapReleaseStatus(ScrapLot sl) {
        int scrapCount = 0;
        int releaseCount = 0;
        int splitOfHoldCount = 0;
        int closeToQDBCount = 0;
        try {
            foreach (PropertyInfo pi in sl.GetType().GetProperties()) {
                if (pi.Name.ToLower().StartsWith("lot") && pi.Name.ToLower().EndsWith("state")) {
                    byte currentValue = (byte)pi.GetValue(sl, null);
                    if (currentValue == (int)GlobalVars.LotStatusOption.Release || currentValue == (int)GlobalVars.LotStatusOption.CloseToQDB) {
                        releaseCount++;
                        // required to update the lot status option
                        if (currentValue == (int)GlobalVars.LotStatusOption.CloseToQDB)
                            closeToQDBCount++;
                    } else if (currentValue == (int)GlobalVars.LotStatusOption.Scrap)
                        scrapCount++;
                    else if (currentValue == (int)GlobalVars.LotStatusOption.SplitOffHold)
                        splitOfHoldCount++;
                }
            }

            sl.ScrapCount = scrapCount;
            sl.ReleaseCount = releaseCount;
            sl.SplitOfHoldCount = splitOfHoldCount;
            sl.CloseToQDBCount = closeToQDBCount;

            ldDMO.UpdateLotScrapReleaseStatus(sl);
            ldDMO.UpdateLotStatus(sl);
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "Issue=" + sl.IssueID.ToString() + " LotNo:" + sl.LotNo.ToString() + "  " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n Scrap Disposition\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = sl.IssueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "UpdateLotScrapReleaseStatus - " + exceptionString });
            throw new Exception(e.Message);
        }
    }

    /// <summary>
    /// Update the all the lots to "RELEASE" Status for a given Lot disposition document
    /// </summary>
    public void ReleaseAll(int issueID) {
        ScrapLot sl = new ScrapLot();
        try {
            sl.IssueID = issueID;
            foreach (PropertyInfo pi in sl.GetType().GetProperties()) {
                if (pi.Name.ToLower().StartsWith("lot") && pi.Name.ToLower().EndsWith("state")) {
                    pi.SetValue(sl, (byte)1, null);
                }
            }

            ldDMO.UpdateLotStatusAll(sl, (int)GlobalVars.LotStatusOption.Release);
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "Issue=" + sl.IssueID.ToString() + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n Release All Disposition\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = sl.IssueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "ReleaseAll - " + exceptionString });
            throw new Exception(e.Message);
        }
    }

    /// <summary>
    /// Update the all the lots to "SCRAP" Status for a given Lot disposition document
    /// </summary>
    public void ScrapAll(int issueID) {
        ScrapLot sl = new ScrapLot();
        try {
            sl.IssueID = issueID;
            foreach (PropertyInfo pi in sl.GetType().GetProperties()) {
                if (pi.Name.ToLower().StartsWith("lot") && pi.Name.ToLower().EndsWith("state")) {
                    pi.SetValue(sl, (byte)2, null);
                }
            }

            ldDMO.UpdateLotStatusAll(sl, (int)GlobalVars.LotStatusOption.Scrap);
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim().Length > 500 ? "Issue=" + sl.IssueID.ToString() + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n Scrap All Disposition\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = sl.IssueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "ScrapAll - " + exceptionString });
            throw new Exception(e.Message);
        }
    }

    public JsonResult GetLotDispositionLotSummary(int issueID) {
        return Json(ldDMO.GetLotDispositionLotSummary(issueID), JsonRequestBehavior.AllowGet);
    }

    /// 
    public ActionResult SubmitDocument(int issueID, bool peRequired, bool mrbRequired) {
        try {
            int appoverCount = ldDMO.SubmitDocument(issueID, peRequired, mrbRequired, (int)Session[GlobalVars.SESSION_USERID]);
            if (appoverCount > 0)
                NotifyApprovers(issueID, (byte)GlobalVars.WorkFLowStepNumber.Step1);
            else {
                // automaically approve current step (Step 1) beacuase there are no approvers in step 1 and move to the next step of approval
                Approve(issueID, (byte)GlobalVars.WorkFLowStepNumber.Step1, ""); // this is the Submit Level Approval

            }

            if (Request.IsAjaxRequest()) {
                return Content("Redirect");
            } else
                return Content("Invalid");
        } 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() + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n SubmitDocument\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "SubmitDocument - " + exceptionString });

            Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
            return Json(new { result = "Error", issueID = issueID, detail = e.Message }, JsonRequestBehavior.AllowGet);
        }
    }

    public void Approve(int issueID, byte currentStep, string comments) {
        int isITARCompliant = 1;
        try {
            bool lastStep = false;
            LotDisposition ltDispo = ldDMO.GetLotDispositionItemForRead(issueID, out isITARCompliant, (int)Session[GlobalVars.SESSION_USERID]);

            bool lastApprover = wfDMO.Approve(_AppSettings, issueID, currentStep, comments, out lastStep, (int)Session[GlobalVars.SESSION_USERID], (int)GlobalVars.DocumentType.LotDisposition, ltDispo.WorkFlowNumber);

            while (lastApprover && !lastStep) {
                currentStep++;
                lastApprover = wfDMO.Approve(_AppSettings, issueID, currentStep, comments, out lastStep, (int)Session[GlobalVars.SESSION_USERID], (int)GlobalVars.DocumentType.LotDisposition, ltDispo.WorkFlowNumber);
                NotifyApprovers(issueID, currentStep);
            }
        } 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() + " Step:" + currentStep + " " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n " + "Approve\r\n" + issueID.ToString() + "\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "Approve - " + exceptionString });
            throw new Exception(e.Message);
        }
    }

    public void Reject(int issueID, byte currentStep, string comments) {
        try {
            if (Session[GlobalVars.SESSION_USERID] != null) {
                wfDMO.Reject(issueID, currentStep, comments, (int)Session[GlobalVars.SESSION_USERID], (int)GlobalVars.DocumentType.LotDisposition);
                NotifyRejectionToOrginator(issueID);
            } else {

                Response.Redirect("~/Account/Login");
            }
        } 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() + " Step:" + currentStep + " " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n Reject\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "Reject - " + exceptionString });
            throw new Exception(e.Message);
        }
    }

    /// <summary>
    /// Get a list of Approvers and the status
    /// </summary>
    public ActionResult GetApproversList([DataSourceRequest] DataSourceRequest request, int issueID, byte step) {
        return Json(MiscDMO.GetApproversListByDocument(issueID, step, (int)GlobalVars.DocumentType.LotDisposition).ToDataSourceResult(request));
    }

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

    public void ReAssignApproval(int issueID, int userIDs, byte step) {
        var email = "";
        try {
            email = wfDMO.ReAssignApproval(issueID, (int)Session[GlobalVars.SESSION_USERID], userIDs, step, (int)GlobalVars.DocumentType.LotDisposition);
        } 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() + " Step:" + step + " " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n ReAssignApproval\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "ReAssignApproval - " + exceptionString });
            throw new Exception(e.Message);
        }
        LotDispositionHelper.ReAssignApproval(_AppSettings, issueID, email);
        try {
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Email", Comments = "ReAssign Approver: " + email });
        } catch { }
    }

    public void ReAssignApproverByAdmin(int issueID, int reAssignApproverFrom, int reAssignApproverTo, byte step) {
        var email = "";
        try {
            email = wfDMO.ReAssignApproval(issueID, reAssignApproverFrom, reAssignApproverTo, step, (int)GlobalVars.DocumentType.LotDisposition);
        } 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() + " Step:" + step + " " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n ReAssignApproval\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "ReAssignApproval - " + exceptionString });
            throw new Exception(e.Message);
        }
        LotDispositionHelper.ReAssignApproverByAdmin(_AppSettings, issueID, email);
        try {
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Email", Comments = "ReAssign Approver: " + email });
        } catch { }
    }

    #region Additional Approvers

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

    public void AddAdditionalApproval(int issueID, byte step, string userIDs) {
        string emailSentList = "";
        var emailArray = "";
        try {
            emailArray = wfDMO.AddAdditionalApproval(issueID, userIDs, step, (int)GlobalVars.DocumentType.LotDisposition);
        } 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() + " Step:" + step + " " + " Userid:" + userIDs + " " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n AddAdditionalApproval\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "AddAdditionalApproval - " + exceptionString });
            throw new Exception(e.Message);
        }
        emailSentList = LotDispositionHelper.AddAdditionalApproval(_AppSettings, issueID, emailSentList, emailArray);
        try {
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Email", Comments = "Additonal Approver: " + emailSentList });
        } catch { }
    }

    #endregion

    public void NotifyApprovers(int issueID, byte currentStep) {
        try {
            List<string> emailIst = MiscDMO.GetApproverEmailListByDocument(@issueID, currentStep, (int)GlobalVars.DocumentType.LotDisposition).Distinct().ToList();
            string emailSentList = LotDispositionHelper.NotifyApprovers(_AppSettings, issueID, emailIst);
            try {
                EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Email", Comments = "Approvers for Step " + currentStep.ToString() + ":" + emailSentList });
            } 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() + " Step:" + currentStep + " " + e.Message.ToString().Substring(0, 250) : e.Message.ToString();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n Lot Dispo - NotifyApprovers\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "AddAdditionalApproval - " + exceptionString });
            throw e;
        }
    }

    public void NotifyRejectionToOrginator(int issueID) {

        string username = Session[GlobalVars.SESSION_USERNAME].ToString();
        List<string> emailIst = ldDMO.GetRejectionOrginatorEmailList(@issueID).Distinct().ToList();
        string userEmail = LotDispositionHelper.NotifyRejectionToOrginator(_AppSettings, issueID, username, emailIst);
        try {
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Email", Comments = "Rejection: " + userEmail });
        } catch { }
    }

    public void UpdateReasonForDisposition(int issueID, string reasonForDisposition) {
        try {
            ldDMO.UpdateReasonForDisposition(issueID, reasonForDisposition);
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n UpdateReasonForDisposition\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "UpdateReasonForDisposition - " + exceptionString });
            throw new Exception(e.Message);
        }
    }

    public ActionResult GetComments([DataSourceRequest] DataSourceRequest request, int issueID) {
        return Json(ldDMO.GetComments(issueID).ToDataSourceResult(request));
    }

    public void InsertComments(int issueID, string Comments) {
        try {
            ldDMO.InsertComments(issueID, Comments, (int)Session[GlobalVars.SESSION_USERID]);
        } catch (Exception e) {
            string detailedException = "";
            try {
                detailedException = e.InnerException.ToString();
            } catch {
                detailedException = e.Message;
            }
            string exceptionString = e.Message.ToString().Trim();
            Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n UpdateCopmments\r\n" + detailedException, System.Diagnostics.EventLogEntryType.Error);
            EventLogDMO.Add(new WinEventLog() { IssueID = issueID, UserID = @User.Identity.Name, DocumentType = "Lot Disposition", OperationType = "Error", Comments = "UpdateCopmments - " + exceptionString });
            throw new Exception(e.Message);
        }
    }

    public ActionResult ExcelLotOpen(IEnumerable<HttpPostedFileBase> Lotfile, int issueID) {
        MRB_DMO mrbDMO = new MRB_DMO(_AppSettings);
        var physicalPath = "";
        try {
            string userIdentityName = @User.Identity.Name;
            foreach (var file in Lotfile) {
                physicalPath = LotDispositionHelper.ExcelLotOpen(ldDMO, issueID, userIdentityName, _AppSettings.LotTempPipeLine, file.FileName, file.InputStream);
            }

            return Content("");
        } catch {
            System.IO.FileInfo f = new System.IO.FileInfo(physicalPath);
            if (f.Exists)
                f.Delete();

            return Content("Incorrect File Format");
        }
    }

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

    public ActionResult GetFileMetaData() {
        return Content("");
    }

    public FileResult DownloadFile(string attachmentID) {

        string fileName = ldDMO.GetFileName(attachmentID);

        var sDocument = System.IO.Path.Combine(_AppSettings.AttachmentFolder + "LotDisposition", fileName);
        var FDir_AppData = _AppSettings.AttachmentFolder;
        if (!sDocument.StartsWith(FDir_AppData)) {
            // 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);
    }
}