using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NPOI.SS.Formula.Functions;
using Siger.ApiCommon.Filters;
using Siger.ApiCommon.Result;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.QmsRepository.Repositories.Interface;
using Siger.Middlelayer.QmsRepository.Response;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.ApiQMS.Controllers
{
    [Consumes("application/json", "multipart/form-data")]
    public class UploadController : BaseController
    {
        private readonly IInspectStandardRepository _inspectStandard;
        private readonly IQmsSensorParameterRepository _qmsSensorParameter;
        private readonly IQmsCellStationRepository _qmsCellStation;
        private readonly IInspectUnhealthyRepository _inspectUnhealthyRepository;
        private readonly IQmsReworkSettingRepository _qmsReworkSetting;
        private readonly IQmsReworkPositionSetting _qmsReworkPosition;
        private readonly ISigerProjectLevelRepository _levelRepository;
        private readonly IInspectStandardMaterialRepository _inspectStandardMaterial;
        private readonly IInspectStandardCategoryRepository _inspectStandardCategory;
        private readonly IInspectStandardItemRepository _inspectStandardItem;
        private readonly IQmsReworkReferenceRepository _qmsReworkReference;
        private readonly IQmsProductAddtion _productAddtion;
        private readonly IQmsProductWarehousing _productWarehousing;
        private readonly IQmscellRepository _qmscellRepository;
        private readonly IQmsmanufacturingMaterial _qmsmanufacturing;
        private readonly IQmsTypeCountSettingRepository _countSettingRepository;

        public UploadController(IInspectStandardRepository inspectStandard, IQmsSensorParameterRepository qmsSensorParameter, IQmsCellStationRepository qmsCellStation,
            IInspectUnhealthyRepository inspectUnhealthyRepository, IQmsReworkSettingRepository qmsReworkSetting,IQmsReworkPositionSetting qmsReworkPosition, IQmsTypeCountSettingRepository countSettingRepository,
            ISigerProjectLevelRepository levelRepository, IInspectStandardMaterialRepository inspectStandardMaterial, IQmscellRepository qmscellRepository, IQmsmanufacturingMaterial qmsmanufacturing,
            IInspectStandardCategoryRepository inspectStandardCategory, IInspectStandardItemRepository inspectStandardItem, IQmsReworkReferenceRepository qmsReworkReference,IQmsProductAddtion productAddtion,IQmsProductWarehousing productWarehousing)
        {
            _inspectStandard = inspectStandard;
            _qmsSensorParameter = qmsSensorParameter;
            _qmsCellStation = qmsCellStation;
            _inspectUnhealthyRepository = inspectUnhealthyRepository;
            _qmsReworkSetting = qmsReworkSetting;
            _qmsReworkPosition = qmsReworkPosition;
            _levelRepository = levelRepository;
            _inspectStandardMaterial = inspectStandardMaterial;
            _inspectStandardCategory = inspectStandardCategory;
            _inspectStandardItem = inspectStandardItem;
            _qmsReworkReference = qmsReworkReference;
            _productAddtion = productAddtion;
            _productWarehousing = productWarehousing;
            _qmscellRepository = qmscellRepository;
            _qmsmanufacturing = qmsmanufacturing;
            _countSettingRepository = countSettingRepository;
        }
        [NoTokenValidateFilter]
        [NoResultFilter]
        [HttpPost]
        public IActionResult UploadImage(IFormFile formFile)
        {
            if (Request.Form?.Files == null)
            {
                throw new BadRequestException(ConfigEnum.UploadFileNotFound);
            }
           
            var date = DateTime.Now.ToString("yyyy-MM-dd");

            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, "image", date);
           
            var files = Request.Form.Files;
            var file = files[0];
            var temporaryFileName = Guid.NewGuid().ToString("N") + FileHelper.GetExtension(file.FileName);
            var fileName = Path.Combine(rootDir, temporaryFileName);

            using (var stream = new FileStream(fileName, FileMode.Create))
            {
                file.CopyTo(stream);
            }
            
            var ret = $"{FileSystemHelper.CommonFileSetting.RequestPath}/image/{date}/{temporaryFileName}";
            return new ObjectResult(new { ret = 1, msg = 1, data = ret });
        }

        [NoTokenValidateFilter]
        [NoResultFilter]
        [HttpPost]
        public IActionResult NewUploadImage(IFormFile formFile)
        {
            if (Request.Form?.Files == null)
            {
                throw new BadRequestException(ConfigEnum.UploadFileNotFound);
            }

            var date = DateTime.Now.ToString("yyyy-MM-dd");

            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, "image", date);
           
            var files = Request.Form.Files;
            var file = files[0];
            var temporaryFileName = Guid.NewGuid().ToString("N") + FileHelper.GetExtension(file.FileName);
            var fileName = Path.Combine(rootDir, temporaryFileName);

            using (var stream = new FileStream(fileName, FileMode.Create))
            {
                file.CopyTo(stream);
            }
            
            var res = new ResponseUploadImage
            {
                url = $"{FileSystemHelper.CommonFileSetting.RequestPath}/image/{date}/{temporaryFileName}",
                name = file.FileName
            };
            return new ObjectResult(res);
        }

        [HttpPost]
        public IActionResult Submit(string templateName)
        {
            if (string.IsNullOrEmpty(templateName))
            {
                throw new BadRequestException(ConfigEnum.FileNameIsEmpty);
            }

            var files = Request.Form.Files;
            if (files == null)
            {
                throw new BadRequestException(ConfigEnum.UploadFileNotFound);
            }

            var file = files[0];
            if (!FileHelper.IsExcelFile(file.FileName))
            {
                throw new BadRequestException(ConfigEnum.IsNotExcelFile);
            }
            var result = Enum.TryParse(typeof(TemplateNameEnums), templateName, true, out var template);
            if (!result)
            {
                throw new BadRequestException(ConfigEnum.TemplateFileNotFound);
            }
            var fileSetting = Config<FileSettings>.Get();
            if (fileSetting == null)
            {
                throw new BadRequestException(CommonEnum.GetCommCfgFailed);
            }

            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ImportFileName);
            
            //save file
            var temporaryFileName = $"{templateName}_{DateTime.Now:yyyyMMddHHmmss}{FileHelper.GetExtension(file.FileName)}";
            var fileName = Path.Combine(rootDir, temporaryFileName);
            try
            {
                using (var stream = new FileStream(fileName, FileMode.Create))
                {
                    file.CopyTo(stream);
                }

                if (!System.IO.File.Exists(fileName))
                {
                    throw new BadRequestException(RequestEnum.ImportFailed);
                }
                var res = UploadAction((TemplateNameEnums)template, fileName);
                if (res.ret == 1)
                {
                    FileHelper.DeleteFile(temporaryFileName);
                    return new ImportObjectResult(res.ret, "1");
                }

                return new ImportObjectResult(res.ret, res.msg);
            }
            catch (Exception e)
            {
                Logger.WriteLineError($"import {templateName} failed, error:" + e.Message);
                throw new BadRequestException(RequestEnum.ImportFailed);
            }
        }

        private CommonImportResult UploadAction(TemplateNameEnums template, string temporaryFilePath)
        {
            CommonImportResult result;
            switch (template)
            {
                case TemplateNameEnums.SensorParameter:
                    result = ImportSensorParameter(temporaryFilePath);
                    break;
                case TemplateNameEnums.InspectUnhealthyTemplate:
                    result = ImportInspectUnhealthy(temporaryFilePath);
                    break;
                case TemplateNameEnums.InspectionStandardList:
                    result = ImportInspectionStandard(temporaryFilePath);
                    break;
                case TemplateNameEnums.ReworkSetting:
                    result = ImportReworkSetting(temporaryFilePath);
                    break;
                case TemplateNameEnums.ReworkPositionSetting:
                    result = ImportReworkPositionSetting(temporaryFilePath);
                    break;
                case TemplateNameEnums.InspectionStandardMaterialList:
                    result = ImportInspectionStandardMaterial(temporaryFilePath);
                    break;
                case TemplateNameEnums.InspectStandardCategoryTemplate:
                    result = ImportInspectionStandardCategory(temporaryFilePath);
                    break;
                case TemplateNameEnums.InspectStandardItemTemplate:
                    result = ImportInspectionStandardItem(temporaryFilePath);
                    break;
                case TemplateNameEnums.ReworkReason:
                    result = ImportReworkReason(temporaryFilePath);
                    break;
                case TemplateNameEnums.WorkCellStation:
                    result = ImportWorkCellStation(temporaryFilePath);
                    break;
                case TemplateNameEnums.Structure:
                    result = ImportStructure(temporaryFilePath);
                    break;
                case TemplateNameEnums.WorkCell:
                    result = ImportWorkCell(temporaryFilePath);
                    break;
                case TemplateNameEnums.ProductAddtion:
                    result = ImportProductAddtion(temporaryFilePath);
                    break;
                case TemplateNameEnums.ProductWarehouse:
                    result = ImportProductWarehouse(temporaryFilePath);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            return result;
        }
        private CommonImportResult ImportProductAddtion(string temporaryFilePath)
        {
            EpPlusExcelHelper<ImportProductAddtion> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<ImportProductAddtion>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }
                var Items = excelHelper.ConvertSheetToList();
                var result = _productAddtion.ImportAddtion(Items, ProjectId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import ImportProductAddtion failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }
        private CommonImportResult ImportProductWarehouse(string temporaryFilePath)
        {
            EpPlusExcelHelper<ImportProductWarehouse> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<ImportProductWarehouse>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }
                var Items = excelHelper.ConvertSheetToList();
                var result = _productWarehousing.ImportWarehouse(Items,UserId, ProjectId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import ImportProductWarehouse failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }
        private CommonImportResult ImportWorkCell(string temporaryFilePath)
        {
            EpPlusExcelHelper<ImportWorkCell> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<ImportWorkCell>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }
                var Items = excelHelper.ConvertSheetToList();
                var result = _qmscellRepository.ImportWorkCell(Items, ProjectId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import ImportReworkReason Standard failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }
        private CommonImportResult ImportReworkReason(string temporaryFilePath)
        {
            EpPlusExcelHelper<ImportReworkReason> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<ImportReworkReason>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }
                var kpiItems = excelHelper.ConvertSheetToList();
                var result = _qmsReworkReference.ImportReference(kpiItems, ProjectId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import ImportReworkReason Standard failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }
        private CommonImportResult ImportWorkCellStation(string temporaryFilePath)
        {
            EpPlusExcelHelper<ImportWorkCellStation> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<ImportWorkCellStation>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                    return new CommonImportResult(0, string.Join(';', messages));
                var Items = excelHelper.ConvertSheetToList();
                var result= _qmsCellStation.ImportWorkCellStation(Items, ProjectId);

                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import ImportWorkCellStation failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }
        private CommonImportResult ImportStructure(string temporaryFilePath)
        {
            EpPlusExcelHelper<ImportManufacturingMaterial > excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<ImportManufacturingMaterial>(temporaryFilePath);
                var Items = excelHelper.ConvertSheetToList();
                var result = _qmsmanufacturing.ImportManufacturingMaterial(Items, ProjectId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import ImportStructure failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }
        private CommonImportResult ImportInspectionStandard(string temporaryFilePath)
        {
            EpPlusForQmsHelper<InspectionStandardLevelTemplate> excelHelper = null;
            try
            {
                excelHelper = new EpPlusForQmsHelper<InspectionStandardLevelTemplate>(temporaryFilePath);
                var levelCount = _levelRepository.GetLevelTitles(0, ProjectId).Count();
                var standards = excelHelper.ConvertSheetToList(levelCount, _levelRepository.GetProjectLanguage(ProjectId));
                var result = _inspectStandard.ImportInspectionStandard(standards, levelCount, ProjectId, UserId, GetAllCategoriess());
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import Inspection Standard failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }

        private CommonImportResult ImportInspectionStandardMaterial(string temporaryFilePath)
        {
            EpPlusForQmsHelper<InspectionStandardMaterialLevelTemplate> excelHelper = null;
            try
            {
                excelHelper = new EpPlusForQmsHelper<InspectionStandardMaterialLevelTemplate>(temporaryFilePath);
                var levelCount = _levelRepository.GetLevelTitles(0, ProjectId).Count();
                var standards = excelHelper.ConvertSheetToList(levelCount, _levelRepository.GetProjectLanguage(ProjectId));
                var result = _inspectStandardMaterial.ImportInspectionStandard(standards, levelCount, ProjectId, UserId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import Material Inspection Standard failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }

        private CommonImportResult ImportSensorParameter(string temporaryFilePath)
        {
            EpPlusExcelHelper<SensorParameter> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<SensorParameter>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }

                var standards = excelHelper.ConvertSheetToList();
                var result = _qmsSensorParameter.ImportInspectDataCountValue(standards, ProjectId, UserId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import Sensor Parameter Count Value Collection failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }

        private CommonImportResult ImportInspectUnhealthy(string temporaryFilePath)
        {
            EpPlusExcelHelper<InspectUnhealthyTemplate> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<InspectUnhealthyTemplate>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }

                var datas = excelHelper.ConvertSheetToList();
                var result = _inspectUnhealthyRepository.ImportInspectUnhealthy(datas, ProjectId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import Inspect Unhealthy failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }
        private CommonImportResult ImportReworkSetting(string temporaryFilePath)
        {
            EpPlusExcelHelper<ReworkSetting> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<ReworkSetting>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }

                var standards = excelHelper.ConvertSheetToList();
                var result = _qmsReworkSetting.ImportReworkSetting(standards, ProjectId);

                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import Inspection Standard failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }
        private CommonImportResult ImportReworkPositionSetting(string temporaryFilePath)
        {
            EpPlusExcelHelper<ReworkPositionReworkSetting> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<ReworkPositionReworkSetting>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }

                var standards = excelHelper.ConvertSheetToList();
                var result =_qmsReworkPosition.ImportReworkSetting(standards, ProjectId);

                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import Inspection Standard failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }

        private CommonImportResult ImportInspectionStandardCategory(string temporaryFilePath)
        {
            EpPlusExcelHelper<InspectStandardCategoryTemplate> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<InspectStandardCategoryTemplate>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }

                var standards = excelHelper.ConvertSheetToList();
                var result = _inspectStandardCategory.ImportInspectStandardCategory(standards, ProjectId);

                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import Inspection Standard Category failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }

        private CommonImportResult ImportInspectionStandardItem(string temporaryFilePath)
        {
            EpPlusExcelHelper<InspectStandardItemTemplate> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<InspectStandardItemTemplate>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }

                var standards = excelHelper.ConvertSheetToList();
                var result = _inspectStandardItem.ImportInspectStandardItem(standards, ProjectId);

                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import Inspection Standard Item failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }

        private Dictionary<string, int> GetAllCategoriess()
        {
            var dict = new Dictionary<string, int>();
            var list = _countSettingRepository.GetList(q => q.status == 1 && q.projectid == ProjectId);
            foreach (var item in list.ToList())
            {
                dict.Add(item.type_name, item.type_code);
            }
            return dict;
        }
    }
}