using Microsoft.AspNetCore.Mvc;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Repository;
using System.Collections.Generic;
using System.Linq;
using Siger.ApiCommon.Result;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.FieldEnum;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Repository.Response;
using Siger.Middlelayer.TlmRepository.Repositories.Interface;
using Siger.Middlelayer.TlmRepository.Request;
using Siger.Middlelayer.TlmRepository.Response;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Dapper;
using System;
using Siger.Middlelayer.Utility.ImportEntities;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Log;
using System.IO;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Repository.Paged;
using Siger.Middlelayer.Common.ModuleEnum;

namespace Siger.ApiTLM.Controllers
{
    public class ToolInstallController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IToolLifeToolInstallRepository _installRepository;
        private readonly ISigerProjectMachineRepository _machineRepository;
        private readonly IToolLifeTechnologyRepository _technologyRepository;
        private readonly IToolLifeToolChoiceSummaryRepository _toolChoiceSummaryRepository;
        private readonly IToolLifeToolTechRepository _toolTechRepository;

        public ToolInstallController(IUnitOfWork unitOfWork, IToolLifeToolInstallRepository installRepository, ISigerProjectMachineRepository machineRepository
            , IToolLifeTechnologyRepository technologyRepository, IToolLifeToolChoiceSummaryRepository toolChoiceSummaryRepository, IToolLifeToolTechRepository toolTechRepository)
        {
            _unitOfWork = unitOfWork;
            _installRepository = installRepository;
            _machineRepository = machineRepository;
            _technologyRepository = technologyRepository;
            _toolChoiceSummaryRepository = toolChoiceSummaryRepository;
            _toolTechRepository = toolTechRepository;
        }

        [HttpPost]
        public IActionResult GetPagedList([FromBody]RequestGetToolInstall request)
        {
            var machineCodes = new List<string>();
            if (string.IsNullOrEmpty(request.machine_code))
            {
                var machineIds = _machineRepository.GetAttributionMachineIds(request.section_id.ToInt(), ProjectId);
                if (!machineIds.Any())
                {
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }
                var codes = _machineRepository.GetList(f => machineIds.Contains(f.id) && f.status != 0).Select(s=>s.code).ToList();
                machineCodes.AddRange(codes);
            }
            else
            {
                machineCodes = new List<string> { request.machine_code };
            }
            //TODO 计算加工件数
            //var labelRep = new LabelCounterRepository(CompanyId, ProjectId);
            var res = new List<ResponseGetInstallList>();
            var data = _installRepository.GetPagedList(machineCodes, request.cutter_number, request.page, request.pagesize, ProjectId, 0);
            foreach (var install in data.Data)
            {
                var model = Mapper<ResponseGetInstallList, ResponseGetInstallList>.Map(install);
                var machine = _machineRepository.Get(t => t.code == model.machine_code && t.projectid == ProjectId && t.status == (int)RowState.Valid);
                model.machine_name = machine?.title ?? "";
                model.machine_code = machine?.code ?? "";
                model.machine_id = install.machine_code;
                var titles = GetPositionByMachineId(machine.id);
                model.section_name = string.Join('-', titles);
                model.process_count = 0;
                    //labelRep.GetProcessCount(install.install_time.ToStr(), install.machine_code.ToInt(), install.cutter_number.ToInt());
                res.Add(model);
            }
            return new PagedObjectResult(res, data.Total, request.page, request.pagesize);
        }
        /// <summary>
        /// 刀具安装记录查询
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        [ProducesResponseType(typeof(ResponseToolInstallInfo),200)]
        public IActionResult GetToolInstallInfo([FromBody] RequestToolInstallInfo req)
        {
            var ret = _installRepository.GetToolInstallInfo(req, ProjectId);
            if (req.toExcel.ToInt() == 0)
            {
                return new PagedObjectResult(ret.Data, ret.Total, req.page, req.pagesize);
            }
            else
            {
                return ExportToolInstallInfo(ret.Data);
            }
        }

        private IActionResult ExportToolInstallInfo(IEnumerable<ResponseToolInstallInfo> list)
        {
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            if (list != null && list.Any())
            {
                EpPlusExcelHelper<ExportToolInstallInfo> helper = null;
                try
                {
                    var dataList = new List<ExportToolInstallInfo>();
                    foreach (var item in list)
                    {
                        switch (item.uninstallReason.ToInt())
                        {
                            case 1:
                                item.uninstallReason = "断刀";
                                break;
                            case 2:
                                item.uninstallReason = "崩刃";
                                break;
                            case 3:
                                item.uninstallReason = "磨损";
                                break;
                            case 4:
                                item.uninstallReason = "寿命到期";
                                break;
                            case 5:
                                item.uninstallReason = "其他原因";
                                break;
                            default:
                                item.uninstallReason = "";
                                break;
                        }
                        item.machineName += $"({item.machineCode})";
                        dataList.Add(Mapper<ResponseToolInstallInfo, ExportToolInstallInfo>.Map(item));
                    }
                    helper = new EpPlusExcelHelper<ExportToolInstallInfo>();
                    var temporaryFileName = $"ToolInstallInfo-{DateTime.Now:yyyyMMddHHmmss}.xlsx";
                    helper.GenerateExcel(dataList, Path.Combine(rootDir, temporaryFileName));
                    return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
                }
                catch (Exception e)
                {
                    Logger.WriteLineError("ExportToolInstallInfo failed, error:" + e);
                    throw new BadRequestException(RequestEnum.ExportFailed);
                }
                finally
                {
                    helper?.Dispose();
                }
            }
            return new ObjectResult(CommonEnum.Fail);
        }


        private List<string> GetPositionByMachineId(int machineId)
        {
            var titleList = new List<string>();
            var machineAttrition = _machineRepository.GetMachineAttributionByMachineId(machineId);
            if (machineAttrition != null)
            {
                var sections = _machineRepository.GetParentSelfLevelSections(machineAttrition.station, ProjectId).ToList();
                if (sections.Any())
                {
                    titleList = sections.Select(t => t.title).ToList();
                    titleList.Reverse();
                }
            }
            return titleList;
        }

        [HttpPost]
        public IActionResult GetInstallDetail([FromBody]RequestGetToolInstall request)
        {
            var res = new List<ResponseGetInstallDetail>();
            var resList = new List<ResponseGetInstallDetail>();
            var data = _installRepository.GetPagedList(new List<string> { request.machine_code }, request.cutter_number, request.page, request.pagesize, ProjectId, 1);
            foreach (var detail in data.Data)
            {
                var stock = _installRepository.GetStockTrace(detail.serial_number, 0, ProjectId);
                if (stock == null)
                {
                    continue;
                }
                var material = _installRepository.GetMaterialList(stock.material_id, stock.material_pn,0, ProjectId).FirstOrDefault();
                if (material == null)
                {
                    continue;
                }

                var supplier = _installRepository.GetSupplier(stock.businessid, ProjectId);
                var model = new ResponseGetInstallDetail
                {
                    cutter_number = detail.cutter_number,
                    machine_code = detail.machine_code,
                    categroy = material.category ?? "",
                    material_id = material.id,
                    material_name = material.name ?? "",
                    supplier = supplier?.name ?? "",
                    quantity = 0
                };
                res.Add(model);
            }
            foreach (var detail in res)
            {
                if (resList.Count(t => t.cutter_number == detail.cutter_number && t.machine_code == detail.machine_code && t.material_id == detail.material_id) > 0)
                {
                    continue;
                }
                var model = Mapper<ResponseGetInstallDetail, ResponseGetInstallDetail>.Map(detail);
                model.quantity = res.Count(t => t.machine_code == detail.machine_code && t.cutter_number == detail.cutter_number && t.material_id == detail.material_id);
                resList.Add(model);
            }
            return new ObjectResult(resList);
        }

        [HttpGet]
        public IActionResult GetMachineCodes()
        {
            var machineCodes = _installRepository.GetList(t => t.status == (int)RowState.Valid && t.project_id == ProjectId &&
                t.install_category == InstallCategory.Install);
            var query = from q in machineCodes
                        select new ResponseIdName
                        {
                            id = q.id,
                            name = q.machine_code
                        };
            return new ObjectResult(query.GroupBy(t => t.name).Select(t => t.FirstOrDefault()).ToList());
        }

        /// <summary>
        /// 获取刀具异常原因列表
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetToolUnusualReason()
        {
            var installList = _installRepository.GetList(t => t.status == (int)RowState.Valid && t.project_id == ProjectId &&
                t.tool_category == (int)InstallCategory.UnInstall && !string.IsNullOrWhiteSpace(t.uninstall_reason)).GroupBy(t => t.uninstall_reason).Select(t => t.FirstOrDefault());
            var res = from q in installList
                      select new
                      {
                          q.id,
                          q.uninstall_reason
                      };
            return new ObjectResult(res.ToList());
        }

        /// <summary>
        /// 获取异常原因片数据
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetUnusualImageData([FromBody]RequestToolUnusualReason req)
        {
            var res = new ResponseGetUnInstallImage();

            var resList = new List<NameCount>();

            var unusualList = _installRepository.GetSupplierUnusualList(req.reason, req.starttime, req.endtime, ProjectId).ToList();
            if (req.xtype.ToInt() == 1)
            {
                var installList = unusualList.GroupBy(t => t.material_id).Select(t => t.FirstOrDefault()).ToList();
                foreach (var tool in installList)
                {
                    var material = _installRepository.GetMaterial(tool.material_id, "", ProjectId);
                    if (material == null)
                    {
                        continue;
                    }
                    resList.Add(new NameCount
                    {
                        count = unusualList.Count(t => t.material_id == tool.material_id),
                        name = material.name
                    });
                }
            }
            else if (req.xtype.ToInt() == 2)
            {
                var groupList = unusualList.GroupBy(t => t.bussiness_id).Select(t => t.FirstOrDefault()).ToList();
                foreach (var install in groupList)
                {
                    resList.Add(new NameCount
                    {
                        name = install.bussiness_name,
                        count = unusualList.Count(t => t.bussiness_id == install.bussiness_id)
                    });
                }
            }

            resList = resList.OrderByDescending(t => t.count).ToList();
            res.x = resList.Select(t => t.name).ToList();
            res.y = resList.Select(t => t.count).ToList();

            return new ObjectResult(res);
        }

        /// <summary>
        /// 通过设备ID获取刀位编号
        /// </summary>
        /// <param name="mid"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetCutterNumbers(string mid)
        {
            var res = _installRepository.GetList(t =>
                    t.status == (int)RowState.Valid && t.project_id == ProjectId && t.machine_code == mid).GroupBy(t => t.cutter_number).Select(t => t.FirstOrDefault())
                .Select(t => new
                {
                    t.id,
                    t.machine_code,
                    t.cutter_number
                }).ToList();

            return new ObjectResult(res);
        }
        /// <summary>
        /// 刀具使用记录查询
        /// </summary>
        /// <param name="reqToolData"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetToolUseData([FromBody]RequestToolUseData reqToolData)
        {
            var firstData = ToolUseData(reqToolData);
            return new PagedObjectResult(firstData.Data, firstData.Total, reqToolData.page, reqToolData.pagesize);
        }


        /// <summary>
        /// 刀具使用记录导出
        /// </summary>
        /// <param name="reqToolData"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult ExportToolUseData([FromBody]RequestToolUseData reqToolData)
        {
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            reqToolData.pagesize = 10000;
            var firstData = ToolUseData(reqToolData);
            var dataList = new List<ToolUseData>();
            //回填安装位置
            foreach (var item in firstData.Data)
            {
                var toolData = Mapper<ResponseToolUseData, ToolUseData>.Map(item);
                dataList.Add(toolData);
            }
            if (dataList != null && dataList.Any())
            {
                EpPlusExcelHelper<ToolUseData> helper = null;
                try
                {
                    helper = new EpPlusExcelHelper<ToolUseData>();
                    var temporaryFileName = $"刀具使用记录-{DateTime.Now:yyyyMMddHHmmss}.xlsx";
                    helper.GenerateExcel(dataList, Path.Combine(rootDir, temporaryFileName), true);
                    return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
                }
                catch (Exception e)
                {
                    Logger.WriteLineError("ExportDict failed, error:" + e);
                    throw new BadRequestException(RequestEnum.ExportFailed);
                }
                finally
                {
                    helper?.Dispose();
                }
            }

            return new ObjectResult(CommonEnum.Fail);
        }

        /// <summary>
        /// 刀具加工能力分析
        /// </summary>
        [HttpPost]
        public IActionResult GetToolProcessData([FromBody]RequestToolProcessData reqToolData)
        {
            var resp = ToolProcessData(reqToolData);
            var pageResp = resp.Skip((reqToolData.page - 1) * reqToolData.pagesize).Take(reqToolData.pagesize);
            return new PagedObjectResult(pageResp, resp.Count);
        }

        [HttpPost]
        public IActionResult ExportToolProcessData([FromBody]RequestToolProcessData reqToolData)
        {
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var firstData = ToolProcessData(reqToolData);
            var dataList = new List<ToolProcessData>();
            //回填安装位置
            foreach (var item in firstData)
            {
                var toolData = Mapper<ResponseToolProcessData, ToolProcessData>.Map(item);
                dataList.Add(toolData);
            }
            if (dataList != null && dataList.Any())
            {
                EpPlusExcelHelper<ToolProcessData> helper = null;
                try
                {
                    helper = new EpPlusExcelHelper<ToolProcessData>();
                    var temporaryFileName = $"刀具加工能力记录-{DateTime.Now:yyyyMMddHHmmss}.xlsx";
                    helper.GenerateExcel(dataList, Path.Combine(rootDir, temporaryFileName));
                    return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
                }
                catch (Exception e)
                {
                    Logger.WriteLineError("ExportDict failed, error:" + e);
                    throw new BadRequestException(RequestEnum.ExportFailed);
                }
                finally
                {
                    helper?.Dispose();
                }
            }

            return new ObjectResult(CommonEnum.Fail);
        }

        /// <summary>
        /// 刀具使用记录信息
        /// </summary>
        /// <param name="reqToolData"></param>
        /// <returns></returns>
        private IPagedCollectionResult<ResponseToolUseData> ToolUseData([FromBody]RequestToolUseData reqToolData)
        {
            //var labelRep = new LabelCounterRepository(CompanyId, ProjectId);
            var firstData = _installRepository.GetToolUseData(reqToolData.Code, reqToolData.Begin, reqToolData.End, reqToolData.Uid, ProjectId, reqToolData.page, reqToolData.pagesize);
            //回填安装位置
            var values = Enum.GetValues(typeof(UninstallReason));
            foreach (var item in firstData.Data)
            {
                var titles = GetPositionByMachineId(item.mid);
                item.Location = string.Join('-', titles);
                //if (item.ProcessCount == 0)
                //{
                //    item.ProcessCount = 0; //labelRep.GetProcessCount(item.InstallTime.ToStr(), item.mid, item.Position.ToInt());
                //}
                if (Enum.TryParse(item.Reason, out UninstallReason reason))
                {
                    item.Reason = EnumHelper.GetEnumDesc(reason);
                }
            }
            return firstData;
        }
        /// <summary>
        /// 刀具加工能力信息(汇总数据来源最高5w条，超过5w请缩小搜索范围)
        /// </summary>
        /// <param name="reqToolData"></param>
        /// <returns></returns>
        private List<ResponseToolProcessData> ToolProcessData(RequestToolProcessData reqToolData)
        {
            var data = _installRepository.GetToolUseData("", reqToolData.Begin, reqToolData.End, 0, ProjectId, reqToolData.page, 50000, reqToolData.MaterialCode, reqToolData.Supplier, reqToolData.ToolName);
            var installData = data.Data;
            var resp = new List<ResponseToolProcessData>();
            //汇总崩刃、寿命终止、磨损信息
            foreach (var item in installData)
            {
                var query = resp.Where(f => f.Material.Equals(item.MaterialCode) && f.Supplier.Equals(item.Supplier) && f.Mid == item.mid).FirstOrDefault();
                if (query != null)
                {
                    //刀具数量
                    query.Count += 1;
                    //加工数量
                    //query.ProcessCount += item.ProcessCount;
                    if (item.Reason != null)
                    {
                        switch (item.Reason.ToInt())
                        {
                            case (int)UninstallReason.Damage:
                                query.Damage += 1;
                                break;
                            case (int)UninstallReason.Broken:
                                query.Broken += 1;
                                break;
                            case (int)UninstallReason.Collapse:
                                query.Collapse += 1;
                                break;
                            default:
                                break;
                        }
                    }
                }
                else
                {

                    if (item.Name != null)
                    {
                        var newData = new ResponseToolProcessData();
                        newData.Count = 1;
                        newData.Damage = 0;
                        newData.Broken = 0;
                        newData.Collapse = 0;
                        newData.Material = item.MaterialCode ?? "";
                        newData.Supplier = item.Supplier ?? "";
                        newData.Mid = item.mid;
                        var titles = GetPositionByMachineId(item.mid);
                        newData.Location = string.Join('-', titles);
                        newData.Name = item.Name ?? "";
                        resp.Add(newData);
                    }
                }
            }
            //计算崩刃、寿命终止、磨损率
            foreach (var item in resp)
            {
                item.Damage = item.Damage * 100 / item.Count;
                item.Collapse = item.Collapse * 100 / item.Count;
                item.Broken = item.Broken * 100 / item.Count;
                item.ProcessCount = item.ProcessCount / item.Count;
            }
            return resp;
        }
        /// <summary>
        /// 产线找设备信息
        /// </summary>
        /// <param name="section"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetMachineBySection(int section)
        {
            return new ObjectResult(_installRepository.GetMachineInfo(section, ProjectId));
        }
        /// <summary>
        /// 寿命对比分析
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        [ProducesResponseType(typeof(ResponseToolLifeAnalysis), 200)]
        public IActionResult ToolLifeAnalysis([FromBody] RequestToolLifeAnalysis request)
        {
            var ret = new ResponseToolLifeAnalysis();
            var technology = _technologyRepository.Get(q =>q.product_id == request.product && q.route_id == request.route && q.status == (int)RowState.Valid
                                                   && q.project_id == ProjectId && q.machine_type == request.machine);
            if (technology == null)
            {
                throw new BadRequestException(RequestEnum.TechnologyNotFound);
            }
            var techTool = _toolTechRepository.GetList(f => f.project_id == ProjectId && f.status != 0 && f.technology_id == technology.id).ToList();
            var serial_nos = _toolChoiceSummaryRepository.GetList(f => f.project_id == ProjectId && f.status != 0 && f.technology_id == technology.id).Select(s=>s.serial_no).ToList();

            var installData = _installRepository.GetList(f => serial_nos.Contains(f.tool_code) && f.project_id == ProjectId && f.status != 0).ToList();

            foreach (var no in serial_nos.Distinct())
            {
                var installInfo = installData.Where(f => f.tool_code == no).OrderByDescending(o => o.uninstall_time).FirstOrDefault();
                if (installInfo == null || installInfo.lastLife.ToInt() == 0)
                {
                    continue;
                }
                ret.detail.Add(new ResponseToolLifeAnalysisDetail
                {
                    ratedLife = techTool.FirstOrDefault()?.rated_life.ToInt() ?? 0,
                    actualLife = installInfo.lastLife.ToInt(),
                    serialNumber = no
                });
            }
            ret.x = ret.detail.Select(s => s.serialNumber).ToList();
            ret.y1 = ret.detail.Select(s => s.ratedLife).ToList();
            ret.y2 = ret.detail.Select(s => s.actualLife).ToList();
            return new ObjectResult(ret);
        }
    }
}