using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Kreta.BusinessLogic.Classes;
using Kreta.BusinessLogic.HelperClasses;
using Kreta.BusinessLogic.HelperClasses.ImportCo;
using Kreta.BusinessLogic.Helpers.ImportExport;
using Kreta.BusinessLogic.Logic;
using Kreta.BusinessLogic.Security;
using Kreta.Core;
using Kreta.Enums;
using Kreta.Enums.ManualEnums;
using Kreta.Enums.ManualEnums.ImportExport;
using Kreta.Resources;
using Kreta.Web.Areas.ImportExport.Models.CommonModels;
using Kreta.Web.Areas.ImportExport.Models.TanuloErtekelesMondatbankImportExport;
using Kreta.Web.Classes;
using Kreta.Web.Helpers;
using Kreta.Web.Models.EditorTemplates;
using Kreta.Web.Security;

namespace Kreta.Web.Areas.ImportExport.Controllers
{
    [MvcRoleClaimsAuthorize(true)]
    [MvcRolePackageDenyAuthorize(KretaClaimPackages.IsSzirIntezmeny.ClaimValue)]
    [MvcRolePackageAuthorize(TanevEnum.AktTanev, KretaClaimPackages.Adminisztrator.ClaimValue)]
    public class TanuloErtekelesMondatbankImportExportController : BaseImportExportController
    {
        #region Fields

        private const string TovabbUrl = @"~/Adminisztracio/SystemSettings";

        #endregion Fields

        #region Properties

        public static string GridName => "TanuloErtekelesMondatbankGrid";
        public static string GridRowTemplateName => "TanuloErtekelesMondatbankGridRowTemplate";

        public static string JavascriptHelperClassName => "TanuloErtekelesMondatbankImportExportHelper";

        public static string ConrtollerName => "TanuloErtekelesMondatbankImportExport";

        #endregion Properties

        #region Constructors

        public TanuloErtekelesMondatbankImportExportController(IUploadFileValidator uploadFileValidator)
        {
            UploadFileValidator = uploadFileValidator ?? throw new ArgumentNullException(nameof(uploadFileValidator));
        }

        #endregion Constructors

        public ActionResult Index()
        {
            var model = new TanuloErtekelesMondatbankImportExportModel
            {
                MaxAllowedFileSizeInBytes = UploadFileValidator.Configuration.ImportMaxAllowedFileSizeInBytes,
                AllowedFileExtensions = UploadFileValidator.Configuration.ImportAllowedFileExtensions
            };
            return View(model);
        }

        #region Sablon

        public ActionResult DownloadTemplate()
        {
            bool isFromSzervezet = false;

            MemoryStream memoryStream = new TanuloErtekelesMondatbankImportExportHelper(ConnectionTypeExtensions.GetSessionConnectionType()).GetTemplate(isFromSzervezet: isFromSzervezet);
            return new FileStreamResult(memoryStream, Core.Constants.ContentTypes.Xlsx) { FileDownloadName = ImportExportTanuloErtekelesMondatbankResource.ImportSablonFileName };
        }

        #endregion Sablon

        #region Export

        [HttpPost]
        [MvcValidateAjaxAntiForgeryToken]
        public string Export()
        {
            MemoryStream memoryStream = new TanuloErtekelesMondatbankImportExportHelper(ConnectionTypeExtensions.GetSessionConnectionType()).GetExport();
            return GetExportFileString(memoryStream);
        }

        public string NemImportalhatoSorokExport()
        {
            MemoryStream memoryStream = new TanuloErtekelesMondatbankImportExportHelper(ConnectionTypeExtensions.GetSessionConnectionType()).GetNemImportalhatoSorokExport();
            return GetExportFileString(memoryStream);
        }

        #endregion Export

        #region Import

        public JsonResult UploadFile(HttpPostedFileBase importFile, int importMuvelet)
        {
            UploadFileValidator.ValidateImportFile(importFile);

            var errorResult = new List<string>();

            Dictionary<int, string> importHeaderList = TanuloErtekelesMondatbankImportExportHelper.ImportHeaderList;
            List<List<string>> importData = ImportExportHelper.GetImportDataFromExcel(importFile.InputStream, importHeaderList, out List<string> fileErrorResultList);
            errorResult.AddRange(fileErrorResultList);

            if (errorResult.Count > 0)
            {
                JsonResult errorJson = ThrowCustomError(errorResult);
                return errorJson;
            }

            new TanuloErtekelesMondatbankImportExportHelper(ConnectionTypeExtensions.GetSessionConnectionType()).SetImportCo(importData, importMuvelet);

            return Json(null);
        }

        public ActionResult OpenImportPreviewPopup()
        {
            TanuloErtekelesMondatbankImportCo importCo = new TanuloErtekelesMondatbankImportExportHelper(ConnectionTypeExtensions.GetSessionConnectionType()).ImportCo;
            List<TanuloErtekelesMondatbankItemCo> coList = importCo.TanuloErtekelesMondatbankCoList;

            var importInfoModel = new TanuloErtekelesMondatbankImportInfoModel
            {
                ImportInfoSummaryList = new ImportInfoSummaryListModel
                {
                    ImportInfoSummaryModelList = new List<ImportInfoSummaryModel>
                    {
                        GetImportInfoSummary(importCo, coList)
                    }
                },
                MainImportItemList = new TanuloErtekelesMondatbankImportItemListModel
                {
                    ImportItemModelList = GetImportItemModelList(importCo, coList)
                },
                NemImportalhatoItemList = new TanuloErtekelesMondatbankImportNemImportalhatoItemListModel
                {
                    NemImportalhatoItemModelList = GetNemImportalhatoItemModelList(importCo.NemImportalhatoItemList)
                }
            };

            var popUpModel = new PopUpModel(importInfoModel, ImportPreviewPopupName);
            popUpModel.AddCancelBtn(popUpModel, "KretaWindowHelper.destroyAllWindow");
            popUpModel.AddBtn(popUpModel, "ImportBtnOk", CommonResource.Importalas, $"{JavascriptHelperClassName}.import", "BtnOk", setDisabledAfterClick: true);
            popUpModel.AddBtn(popUpModel, "NemImportalhatoSorokExportBtnOk", ImportExportCommonResource.NemImportalhatoSorokExportalasa, $"{JavascriptHelperClassName}.nemImportalhatoSorokExport", "BtnOk");
            return PartialView(Constants.General.PopupView, popUpModel);
        }

        private static ImportInfoSummaryModel GetImportInfoSummary(TanuloErtekelesMondatbankImportCo importCo, List<TanuloErtekelesMondatbankItemCo> coList)
        {
            List<TanuloErtekelesMondatbankImportJsonItemCo> mainImportJsonItemList = importCo.MainImportJsonItemList;
            int insertRowCount = mainImportJsonItemList?.Count(x => x.Operation == (int)ImportItemOperationEnum.Insert) ?? 0;
            int updateRowCount = mainImportJsonItemList?.Count(x => x.Operation == (int)ImportItemOperationEnum.Update) ?? 0;
            int deleteRowCount = importCo.ImportMuvelet == (int)ImportMuveletEnum.DeleteAndInsert ? coList.Count : 0;
            int unchangedRowCount;
            switch (importCo.ImportMuvelet)
            {
                case (int)ImportMuveletEnum.DeleteAndInsert:
                    unchangedRowCount = 0;
                    break;

                case (int)ImportMuveletEnum.InsertAndUpdate:
                    unchangedRowCount = coList.Count - updateRowCount;
                    break;

                default:
                    unchangedRowCount = coList.Count;
                    break;
            }

            int invalidRowCount = importCo.NemImportalhatoItemList.Count;
            var importInfoSummary = new ImportInfoSummaryModel
            {
                ImportName = ImportExportTanuloErtekelesMondatbankResource.ImportDefaultSheetName,
                InsertRowCount = insertRowCount.ToString(),
                UpdateRowCount = updateRowCount.ToString(),
                DeleteRowCount = deleteRowCount.ToString(),
                UnchangedRowCount = unchangedRowCount.ToString(),
                InvalidRowCount = invalidRowCount.ToString()
            };
            return importInfoSummary;
        }

        private List<TanuloErtekelesMondatbankImportItemModel> GetImportItemModelList(TanuloErtekelesMondatbankImportCo importCo, List<TanuloErtekelesMondatbankItemCo> coList)
        {
            var importItemModelList = new List<TanuloErtekelesMondatbankImportItemModel>();
            List<TanuloErtekelesMondatbankImportJsonItemCo> mainImportJsonItemList = importCo.MainImportJsonItemList;
            if (mainImportJsonItemList == null)
            {
                if (!(coList.Count > 0))
                {
                    return importItemModelList;
                }

                mainImportJsonItemList = new List<TanuloErtekelesMondatbankImportJsonItemCo>();
            }

            //NOTE: Hozzáadjuk azokat a az elemeket, amik az excel-ből jöttek!
            foreach (TanuloErtekelesMondatbankImportJsonItemCo importJsonItem in mainImportJsonItemList)
            {
                importItemModelList.Add(new TanuloErtekelesMondatbankImportItemModel
                {
                    RovidNev = importJsonItem.RovidNev ?? string.Empty,
                    Szoveg = importJsonItem.Szoveg,
                    TanuloErtekelesTipusNev = importJsonItem.TanuloErtekelesTipusId.IsEntityId() ? importJsonItem.TanuloErtekelesTipusId.GetDisplayName<ErtekelesTipusEnum>(ClaimData.SelectedTanevID.Value) : CommonResource.Mind,
                    EvfolyamTipusNev = importJsonItem.EvfolyamTipusId.IsEntityId() ? importJsonItem.EvfolyamTipusId.GetDisplayName<EvfolyamTipusEnum>(ClaimData.SelectedTanevID.Value) : CommonResource.Mind,
                    TantargyNev = importJsonItem.TantargyNev ?? CommonResource.Mind,
                    Operation = importJsonItem.Operation
                });
            }

            //NOTE: Hozzáadjuk azokat a az elemeket, amik az adatbázisból jöttek!
            foreach (TanuloErtekelesMondatbankItemCo co in coList)
            {
                if (!mainImportJsonItemList.Select(x => x.Id).Contains(co.Id))
                {
                    importItemModelList.Add(new TanuloErtekelesMondatbankImportItemModel
                    {
                        RovidNev = co.RovidNev ?? string.Empty,
                        Szoveg = RichTextLogic.CutHtmlTagsAndDecodeAndBR2Space(co.Szoveg),
                        TanuloErtekelesTipusNev = co.TanuloErtekelesTipusId.IsEntityId() ? co.TanuloErtekelesTipusId.GetDisplayName<ErtekelesTipusEnum>(ClaimData.SelectedTanevID.Value) : CommonResource.Mind,
                        EvfolyamTipusNev = co.EvfolyamTipusId.IsEntityId() ? co.EvfolyamTipusId.GetDisplayName<EvfolyamTipusEnum>(ClaimData.SelectedTanevID.Value) : CommonResource.Mind,
                        TantargyNev = co.TantargyNev ?? CommonResource.Mind,
                        Operation = importCo.ImportMuvelet == (int)ImportMuveletEnum.DeleteAndInsert ? (int)ImportItemOperationEnum.Delete : (int)ImportItemOperationEnum.Default
                    });
                }
            }

            return importItemModelList.OrderBy(x => x.RovidNev).ThenBy(x => x.Szoveg).ThenByDescending(x => x.OperationText).ToList();
        }

        private List<TanuloErtekelesMondatbankImportNemImportalhatoItemModel> GetNemImportalhatoItemModelList(List<TanuloErtekelesMondatbankImportItemCo> nemImportalhatoItemList)
        {
            var nemImportalhatoItemModelList = new List<TanuloErtekelesMondatbankImportNemImportalhatoItemModel>();
            foreach (TanuloErtekelesMondatbankImportItemCo nemImportalhatoItem in nemImportalhatoItemList)
            {
                nemImportalhatoItemModelList.Add(new TanuloErtekelesMondatbankImportNemImportalhatoItemModel
                {
                    RovidNevImportData = nemImportalhatoItem.RovidNevImportData ?? string.Empty,
                    SzovegImportData = nemImportalhatoItem.SzovegImportData ?? string.Empty,
                    TanuloErtekelesTipusImportData = nemImportalhatoItem.TanuloErtekelesTipusImportData ?? string.Empty,
                    EvfolyamTipusImportData = nemImportalhatoItem.EvfolyamTipusImportData ?? string.Empty,
                    TantargyImportData = nemImportalhatoItem.TantargyImportData ?? string.Empty,
                    ErrorList = string.Join(Environment.NewLine, nemImportalhatoItem.ErrorList)
                });
            }

            return nemImportalhatoItemModelList.OrderBy(x => x.RovidNevImportData).ThenBy(x => x.SzovegImportData).ToList();
        }

        public ActionResult Import()
        {
            if (ModelState.IsValid)
            {
                TanuloErtekelesMondatbankImportCo importCo = new TanuloErtekelesMondatbankImportExportHelper(ConnectionTypeExtensions.GetSessionConnectionType()).ImportCo;
                new ImportExportHelper(ConnectionTypeExtensions.GetSessionConnectionType()).Import(new { ImportJson = importCo }, importCo.ImportMuvelet, isTorlesCsakImportalt: false);
                return Content(Url.Content(TovabbUrl));
            }

            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        #endregion Import
    }
}