using System;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
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.Redis.Model;
using Siger.Middlelayer.Redis.Repositories;
using Siger.Middlelayer.Redis.Utility;
using Siger.Middlelayer.ToolRepository.Entities;
using Siger.Middlelayer.ToolRepository.Repositories.Interface;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.ApiTools.Controllers
{
    [Consumes("application/json", "multipart/form-data")]
    public class UploadController : BaseController
    {
        private readonly ISigerProjectToolRepository _sigerProjectToolRepository;
        private readonly ISigerProjectToolCutterLocationTrueRepository _locationTrueRepository;
        private readonly ISigerToolChangeRecordRepository _toolChangeRecordRepository;

        public UploadController(ISigerProjectToolRepository sigerProjectToolRepository,
            ISigerProjectToolCutterLocationTrueRepository locationTrueRepository, ISigerToolChangeRecordRepository toolChangeRecordRepository)
        {
            _sigerProjectToolRepository = sigerProjectToolRepository;
            _locationTrueRepository = locationTrueRepository;
            _toolChangeRecordRepository = toolChangeRecordRepository;
        }

        [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);
            }
            
            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);
            
            //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.ToolsInfo:
                    result = ImportToolSupplierInfo(temporaryFilePath);
                    break;
                case TemplateNameEnums.ToolsLocationInfo:
                    result = ImportToolLocationInfo(temporaryFilePath);
                    break;
                case TemplateNameEnums.ToolsChange:
                    result = ImportToolChangeInfo(temporaryFilePath);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            return result;
        }

        /// <summary>
        /// 刀具信息导入
        /// </summary>
        /// <param name="temporaryFilePath"></param>
        /// <returns></returns>
        private CommonImportResult ImportToolSupplierInfo(string temporaryFilePath)
        {
            EpPlusExcelHelper<ToolSupplierList> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<ToolSupplierList>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }
                var products = excelHelper.ConvertSheetToList();
                var result = _sigerProjectToolRepository.ImportTools(products, ProjectId);
                return result;
            }
            catch (Exception e)
            {
                Logger.WriteLineError("ImportToolSupplierInfo failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }

        /// <summary>
        /// 刀位信息导入
        /// </summary>
        /// <param name="temporaryFilePath"></param>
        /// <returns></returns>
        private CommonImportResult ImportToolLocationInfo(string temporaryFilePath)
        {
            EpPlusExcelHelper<ToolLocationList> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<ToolLocationList>(temporaryFilePath);
                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }
                var products = excelHelper.ConvertSheetToList().ToList();
                var result = _locationTrueRepository.ImportToolLocations(products, ProjectId);

                if (result.ret == 1)
                {
                    var repository = new RatedLifeConfigRepository(CompanyId, ProjectId, false);
                    var targetRepository = new MonitorTargetRepository(CompanyId, ProjectId, false);
                    //sync redis
                    foreach (var info in result.ToolImportInfoes)
                    {
                        repository.AddRateLifeConfig(ProgramType.mainProgram+info.ProgramNo, info.RateLife, info.ToolLocationName, info.MachineId, info.SpindleNo,
                            info.type,0,1);

                        targetRepository.AddMonitorTarget(info.SpindleNo, info.ToolLocationName, info.ProgramNo, info.MachineId);
                    }
                    repository.Dispose();
                    targetRepository.Dispose();
                }
                return new CommonImportResult(result.ret, result.msg);
            }
            catch (Exception e)
            {
                Logger.WriteLineError("ImportToolLocationInfo failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }

        /// <summary>
        /// 换刀记录导入
        /// </summary>
        /// <param name="temporaryFilePath"></param>
        /// <returns></returns>
        private CommonImportResult ImportToolChangeInfo(string temporaryFilePath)
        {
            EpPlusExcelHelper<ToolChangeList> excelHelper = null;
            try
            {
                excelHelper = new EpPlusExcelHelper<ToolChangeList>(temporaryFilePath);

                var messages = excelHelper.CheckExcel();
                if (messages.Any())
                {
                    return new CommonImportResult(0, string.Join(';', messages));
                }
                
                var products = excelHelper.ConvertSheetToList();
                var result = _toolChangeRecordRepository.ImportToolChange(products, ProjectId);

                if (result.ret == 1)
                {
                    var repository = new ChangeToolRepository(CompanyId, ProjectId, false);
                    //sync redis
                    foreach (var info in result.ToolChangeImportInfoes)
                    {
                        var toolChange = new siger_tool_change_record
                        {
                            machine_id = info.MachineId,
                            rating_life = info.RatedLife,
                            programno = info.ProgramNo,
                            mainaxis = info.SpindleName,
                            change_reason = info.Reason,
                            tool_name = info.ToolName,
                            change_time = info.ChangeTime,
                            tool_no = info.ToolNo
                        };
                        var model = Mapper<siger_tool_change_record, RedisChangeRecordModel>.Map(toolChange);
                        repository.AddChangeToolsRecord(model, UnixTimeHelper.ConvertStringDateTime(info.ChangeTime.ToString()));
                    }
                    repository.Dispose();
                }
                return new CommonImportResult(result.ret, result.msg);
            }
            catch (Exception e)
            {
                Logger.WriteLineError("ImportToolChangeInfo failed，error: " + e.Message);
                throw;
            }
            finally
            {
                excelHelper?.Dispose();
            }
        }
    }
}