using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Exceptions;
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.Repository.Repositories.Interface;
using Siger.Middlelayer.TpmRepository.Repositories.Interface;
using Siger.Middlelayer.TpmRepository.Request;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.ApiTPM.Controllers
{
    [Consumes("application/json", "multipart/form-data")]
    public class UploadController : BaseController
    {
        private readonly ISparepartRepository _sparepartRepository;
        private readonly ISparepartTypeRepository _sparepartTypeRepository;
        private readonly IFaultTypeRepository _faultTypeRepository;
        private readonly IPlanRepository _planRepository;
        private readonly ISigerProjectLevelRepository _levelRepository;
        private readonly ISigerAndonExpectionTypeRepository _andonExpectionTypeRepository;

        public UploadController(ISparepartRepository sparepartRepository, ISparepartTypeRepository sparepartTypeRepository,
            IFaultTypeRepository faultTypeRepository, IPlanRepository planRepository, ISigerProjectLevelRepository levelRepository,
            ISigerAndonExpectionTypeRepository andonExpectionTypeRepository)
        {
            _sparepartRepository = sparepartRepository;
            _sparepartTypeRepository = sparepartTypeRepository;
            _faultTypeRepository = faultTypeRepository;
            _planRepository = planRepository;
            _levelRepository = levelRepository;
            _andonExpectionTypeRepository = andonExpectionTypeRepository;
        }

        [HttpPost]
        public IActionResult UploadThumbnail([FromBody]RequestUploadThumbnail request)
        {
            if (string.IsNullOrWhiteSpace(request.image))
            {
                throw new BadRequestException(CommonEnum.Fail);
            }

            var date = DateTime.Now.ToString("yyyy-MM-dd");
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, "image", date);
            
            try
            {
                var baseImage = request.image.Replace("data:image/png;base64,", "").Replace("data:image/jpg;base64,", "").Replace("data:image/jpeg;base64,", "");
                var bit = Convert.FromBase64String(baseImage);
                var temporaryFileName = Guid.NewGuid().ToString("N") + ".png";
                var fileName = Path.Combine(rootDir, temporaryFileName);
                using (var ms = new MemoryStream(bit))
                {
                    using (var stream = new FileStream(fileName, FileMode.Create))
                    {
                        ms.CopyTo(stream);
                    }
                }
                
                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/image/{date}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("upload thumbnial failed, error: " + e);
                throw new BadRequestException(CommonEnum.Fail);
            }
        }

        [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);
          
            if (!Directory.Exists(rootDir))
            {
                Directory.CreateDirectory(rootDir);
            }
            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);
            }
            
            return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/image/{date}/{temporaryFileName}");
        }

        [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);
            if (!Directory.Exists(rootDir))
            {
                Directory.CreateDirectory(rootDir);
            }

            //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.FaultType:
                    result = ImportFaultType(temporaryFilePath);
                    break;
                case TemplateNameEnums.SparepartTypeList:
                    result = ImportSparepartType(temporaryFilePath);
                    break;
                case TemplateNameEnums.SparepartList:
                    result = ImportSparepart(temporaryFilePath);
                    break;
                case TemplateNameEnums.LevelPlanList:
                    result = ImportLevelPlan(temporaryFilePath);
                    break;
                case TemplateNameEnums.LevelPlanListSkf:
                    result = ImportLevelPlanSkf(temporaryFilePath);
                    break;
                case TemplateNameEnums.AndonExpectionType:
                    result = ImportAndonExpection(temporaryFilePath);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            return result;
        }

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

                var types = excelHelper.ConvertSheetToList();
                var result = _faultTypeRepository.ImportFaultType(types, ProjectId, UserId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import FaultType failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }

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

                var types = excelHelper.ConvertSheetToList();
                var result = _sparepartRepository.ImportSparepart(types, ProjectId, UserId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import Sparepart failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }

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

                var types = excelHelper.ConvertSheetToList();
                var result = _sparepartTypeRepository.ImportSparepartType(types, ProjectId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import SparepartType failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }

        private CommonImportResult ImportLevelPlan(string temporaryFilePath)
        {
            try
            {
                var excelHelper = new EpPlusForTpmHelper(temporaryFilePath);
                var levelCount = _levelRepository.GetLevelTitles(0, ProjectId).Count();
                var types = excelHelper.ConvertSheetToList(levelCount, _planRepository.GetProjectLanguage(ProjectId));
                if (!types.Any())
                {
                    throw new BadRequestException(CommonEnum.NoData);
                }
                var result = _planRepository.ImportLevelPlanList(types, ProjectId, UserId, levelCount);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import LevelPlan failed，error: " + e.Message);
                throw;
            }
        }

        private CommonImportResult ImportLevelPlanSkf(string temporaryFilePath)
        {
            try
            {
                var excelHelper = new EpPlusExcelHelper<LevelPlanListSkf>(temporaryFilePath);
                var types = excelHelper.ConvertSheetToList();
                if (!types.Any())
                {
                    throw new BadRequestException(CommonEnum.NoData);
                }
                var result = _planRepository.ImportLevelPlanListSkf(types, ProjectId, UserId, 0);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Import LevelPlan failed，error: " + e.Message);
                throw;
            }
        }

        private CommonImportResult ImportAndonExpection(string temporaryFilePath)
        {
            try
            {
                var excelHelper = new EpPlusExcelHelper<ImportAndonExpection>(temporaryFilePath);
                var types = excelHelper.ConvertSheetToList();
                if (!types.Any())
                {
                    throw new BadRequestException(CommonEnum.NoData);
                }
                var result = _andonExpectionTypeRepository.ImportAndonExpection(types, ProjectId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("ImportAndonExpection failed，error: " + e.Message);
                throw;
            }
        }
    }
}