using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
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.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Request;
using Siger.Middlelayer.Repository.Response;
using Siger.Middlelayer.TpmRepository.Entities;
using Siger.Middlelayer.TpmRepository.Repositories.Interface;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;
using UnixTimeHelper = Siger.Middlelayer.Common.Helpers.UnixTimeHelper;

namespace Siger.ApiTPM.Controllers
{
    public class SparepartController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerProjectMachineRepository _machineRepository;
        private readonly ISparepartRepository _projectSparepartRepository;
        private readonly ISparepartTypeRepository _sparepartTypeRepository;
        private readonly ISparepartRecordRepository _recordRepository;
        private readonly ISparepartMachineRepository _sparepartMachineRepository;
        private readonly ISigerProjectMachineTypeRepository _machineTypeRepository;
        private readonly ISigerProjectSparepartCodeRepository _codeRepository;
        private readonly ISigerProjectMachineAttributionRepository _attributionRepository;
        public SparepartController(IUnitOfWork unitOfWork, ISparepartRepository projectSparepartRepository, ISparepartMachineRepository sparepartMachineRepository,
            ISigerProjectMachineTypeRepository machineTypeRepository, ISparepartRecordRepository recordRepository, ISigerProjectMachineRepository machineRepository,
            ISparepartTypeRepository sparepartTypeRepository, ISigerProjectSparepartCodeRepository codeRepository, ISigerProjectMachineAttributionRepository attributionRepository)
        {
            _unitOfWork = unitOfWork;
            _machineRepository = machineRepository;
            _sparepartMachineRepository = sparepartMachineRepository;
            _recordRepository = recordRepository;
            _projectSparepartRepository = projectSparepartRepository;
            _machineTypeRepository = machineTypeRepository;
            _sparepartTypeRepository = sparepartTypeRepository;
            _codeRepository = codeRepository;
            _attributionRepository = attributionRepository;
        }

        [HttpGet]
        public IActionResult SearchSparepartsBySection(string machinetype1, string machinetype2, string keyword,
            string s_is_standard, string s_is_substitute, string s_report, int lastCheckValsparepart, string lastCheckVal, int charger, string key,string order,
            int page = 1, int pagesize = PageSize)
        {
            var response = new List<ResponseGetSparepart>();
            var lastCheckList = new List<int>();
            if (!string.IsNullOrWhiteSpace(lastCheckVal))
            {
                foreach (var check in lastCheckVal.Split(','))
                {
                    lastCheckList.Add(int.Parse(check));
                }
            }
            
            var list = _projectSparepartRepository.GetPagedList(machinetype1.ToInt(), machinetype2.ToInt(), keyword, s_is_standard, s_is_substitute,
                s_report, lastCheckValsparepart, lastCheckList, charger, ProjectId, page, pagesize, key, order);

            foreach (var sparepart in list.Data)
            {
                var stockStatus = 1;
                if (sparepart.sku < sparepart.mini_sku) //报警
                {
                    stockStatus = 2;
                }
                else if (sparepart.sku >= sparepart.mini_sku)
                {
                    stockStatus = 1; //正常
                }

                //领用状态
                var data = Mapper<ResponseGetSparepart, ResponseGetSparepart>.Map(sparepart);
                data.stock_status = stockStatus;
                var result = GetSparepartInOut(sparepart.id);
                data.thisMonth_in = result[0];
                data.thisMonth_out = result[1];
                data.lastMonth_out = result[2];
                if (data.thisMonth_out > data.lastMonth_out)
                {
                    data.out_status = 1; //领用异常报警
                }
                response.Add(data);
            }

            return new PagedObjectResult(response, list.Total, page, pagesize);
        }

        private int GetSparepartCount(int sparepartId, int startTime, int endTime, int type)
        {
            //type=>1 出库 type=>2入库
            var count = _recordRepository.GetList(q => q.sparepartid == sparepartId && q.type == type
                                                                                    && q.create_time >= startTime && q.create_time < endTime
                                                                                    && q.projectid == ProjectId && q.status == (int) RowState.Valid)
                .Sum(q => q.number);

            return count;
        }

        [HttpGet]
        public IActionResult GetOneSparepartItem(int id)
        {
            var entity = _projectSparepartRepository.Get(q => q.id == id && q.status == (int)RowState.Valid && q.projectid == ProjectId);
            if (entity == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var typeTitle = _sparepartTypeRepository.Get(q => q.id == entity.typeid && q.status == (int) RowState.Valid && q.projectid == ProjectId);

            var data = Mapper<siger_project_sparepart, ResponseGetSparepart>.Map(entity);
            data.typeTitle = typeTitle != null ? typeTitle.title : "";

            var result = GetSparepartInOut(entity.id);
            data.thisMonth_in = result[0];
            data.thisMonth_out = result[1];
            data.lastMonth_out = result[2];

            var stockStatus = 1; //正常
            //库存是否报警
            if (entity.purchase_status == 1)
            {
                stockStatus = 3; //采购中
            }
            else if (entity.sku < entity.mini_sku) //报警
            {
                stockStatus = 2;
            }

            data.stock_status = stockStatus;

            if (entity.is_common == 1)
            {
                data.machinetitle = "300091";//通用型
            }
            else
            {
                var title = string.Empty;
                var machines = _sparepartMachineRepository.GetList(q => q.sparepartid == entity.id && q.status == (int) RowState.Valid && q.projectid == ProjectId);
                foreach (var machine in machines.ToList())
                {
                    if (machine.machineid != 0)
                    {
                        var machineEntity = _machineRepository.Get(q =>
                            q.id == machine.machineid && q.status == (int) RowState.Valid && q.projectid == ProjectId);
                        if (machineEntity != null)
                        {
                            title += machineEntity.title + ",";
                        }
                    }
                    else if(machine.machinetypeid != 0)
                    {
                        var machineTypeEntity = _machineTypeRepository.Get(q =>
                            q.id == machine.machinetypeid && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                        if (machineTypeEntity != null)
                        {
                            title += machineTypeEntity.title + ",";
                        }
                    }
                }

                data.machinetitle = title.TrimEnd(',');
            }

            var time = UnixTimeHelper.GetNow();
            var starttime = UnixTimeHelper.GetMouthUnix();
            var times = new List<string>();
            var nowTime = DateTime.Now;
            var numTimes = new Dictionary<string, int>();
            for (var i = 1; i <= nowTime.Day; i++)
            {
                numTimes.Add(nowTime.Month + "-" + i, 0);
            }
            var records = _recordRepository.GetList(t =>
                t.projectid == ProjectId && t.create_time <= time && t.create_time >= starttime &&
                t.sparepartid == id && t.type == (int) StockCategory.OutStock && t.status == (int) RowState.Valid).OrderBy(t => t.create_time).ToList();
            var datas = records.GroupBy(t=>UnixTimeHelper.ConvertIntDate(t.create_time)).ToList();
            foreach (var record in datas)
            {
                if (record.Any())
                {
                    var count = 0;
                    foreach(var item in record)
                    {
                        count += item.number;
                    }
                    var createtime = UnixTimeHelper.ConvertIntDate(record.ToList()[0].create_time).ToDateTime();
                    var daytime = createtime.Month + "-" + createtime.Day;
                    if (numTimes.ContainsKey(daytime))
                    {
                        numTimes[daytime] = count;
                    }
                }
            }
            data.nums = numTimes.Select(t => t.Value).ToList();
            data.times = numTimes.Select(t => t.Key).ToList();

            //获取入库详情
            var codes = _codeRepository.GetList(q => q.sparepart_id == id && q.project_id == ProjectId && q.status == (int) RowState.Valid).ToList();
            if (codes.Any())
            {
                foreach (var code in codes)
                {
                    data.spareparts.Add(new SparepartInstockInfo
                    {
                        code = code.sparepart_code,
                        repair_count = code.repair_count
                    });
                }
            }

            return new ObjectResult(data);
        }

        [HttpPost]
        public IActionResult AddTypeSparepart([FromBody] RequestAddSparepart request)
        {
            var isExist = _projectSparepartRepository.Get(q => q.code == request.code && q.status == (int) RowState.Valid && q.projectid == ProjectId);
            if (isExist != null)
            {
                throw new ServerException(300055);
            }

            var entity = new siger_project_sparepart
            {
                brand = request.brand,
                code = request.code,
                create_mid = UserId,
                projectid = ProjectId,
                create_ip = ServerIpAddress,
                description = request.description,
                delivery_time = request.delivery_time.ToInt(),
                image = !string.IsNullOrWhiteSpace(request.image) ? request.image : "",
                material = request.material,
                max_sku = request.max_sku.ToInt(),
                mini_sku = request.mini_sku.ToInt(),
                price = request.price.ToDouble(),
                param = request.param,
                purchase_status = request.purchase_status.ToInt(),
                remark = request.remark,
                sku = request.sku.ToInt(),
                supplier = request.supplier,
                is_standard = request.is_standard.ToInt(),
                is_substitute = request.is_substitute.ToInt(),
                is_common = request.is_common.ToInt(),
                title = request.title,
                time = UnixTimeHelper.GetNow(),
                unit = request.unit,
                warehouse = request.warehouse,
                sku_report_mid = request.sku_report_mid,
                typeid = request.spareparttype.ToInt(),
                repair_upperlimit = request.repair_upperlimit.ToDouble(),
                approvaluser_mid = request.approvaluser.ToInt(),
                sku_limit = request.sku_limit.ToInt()
            };
            _projectSparepartRepository.Insert(entity);
            if (request.is_common.ToInt() == 1)
            {
                if (_unitOfWork.Commit() < 0)
                {
                    throw new BadRequestException(CommonEnum.Fail);
                }
            }
            else if(request.is_common.ToInt() == 0)//非标准件需要关联设备
            {
                if (request.subsu.ToInt() == 1) //设备类型
                {
                    if (_unitOfWork.Commit() < 0)
                    {
                        throw new BadRequestException(CommonEnum.Fail);
                    }

                    var machineTypeIds = _machineTypeRepository.GetMachineTypeIds(request.machinetype.ToInt(), ProjectId);
                    var sparepart = _projectSparepartRepository.Get(q =>
                        q.code == request.code && q.status == (int) RowState.Valid && q.projectid == ProjectId);
                    
                    foreach (var machineTypeId in machineTypeIds)
                    {
                        var sparepartMachine = new siger_project_sparepart_machine
                        {
                            machinetypeid = machineTypeId,
                            projectid = ProjectId,
                            sparepartid = sparepart.id,
                        };
                        _sparepartMachineRepository.Insert(sparepartMachine);
                    }

                    if (_unitOfWork.Commit() < 0)
                    {
                        throw new BadRequestException(CommonEnum.Fail);
                    }
                }
                else if (request.subsu.ToInt() == 2) //产线层级
                {
                    var machine = _machineRepository.Get(t =>
                        t.id == request.sectionid.ToInt() && t.projectid == ProjectId && t.status == (int) RowState.Valid);
                    if (machine == null)
                    {
                        throw new ServerException(300056);
                    }
                    if (_unitOfWork.Commit() < 0)
                    {
                        throw new BadRequestException(CommonEnum.Fail);
                    }

                    var sparepart = _projectSparepartRepository.Get(q =>
                        q.code == request.code && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                    var sparepartMachine = new siger_project_sparepart_machine
                    {
                        machineid = machine.id,
                        projectid = ProjectId,
                        sparepartid = sparepart.id,
                    };
                    _sparepartMachineRepository.Insert(sparepartMachine);
                    if (_unitOfWork.Commit() < 0)
                    {
                        throw new BadRequestException(CommonEnum.Fail);
                    }
                }
            }

            return new ObjectResult(CommonEnum.Succefull);
        }

        [HttpPost]
        public IActionResult EditSparepart([FromBody] RequestUpdateSparepart request)
        {
            var entity = _projectSparepartRepository.Get(q => q.id == request.id && q.status == (int)RowState.Valid && q.projectid == ProjectId);
            if (entity == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var isExist = _projectSparepartRepository.Get(q => q.code == request.code && q.status == (int)RowState.Valid && q.id != request.id && q.projectid == ProjectId);
            if (isExist != null)
            {
                throw new ServerException(300055);
            }

            entity.brand = request.brand;
            entity.code = request.code;
            entity.description = request.description;
            entity.delivery_time = request.delivery_time.ToInt();
            if (!string.IsNullOrWhiteSpace(request.image))
            {
                entity.image = request.image;
            }
            entity.material = request.material;
            entity.max_sku = request.max_sku.ToInt();
            entity.mini_sku = request.mini_sku.ToInt();
            entity.price = request.price.ToDouble();
            entity.param = request.param;
            entity.purchase_status = request.purchase_status.ToInt();
            entity.remark = request.remark;
            entity.sku = request.sku.ToInt();
            entity.supplier = request.supplier;
            entity.is_standard = request.is_standard.ToInt();
            entity.is_substitute = request.is_substitute.ToInt();
            entity.is_common = request.is_common.ToInt();
            entity.title = request.title;
            entity.time = UnixTimeHelper.GetNow();
            entity.unit = request.unit;
            entity.warehouse = request.warehouse;
            entity.sku_report_mid = request.sku_report_mid;
            entity.typeid = request.spareparttype.ToInt();
            entity.repair_upperlimit = request.repair_upperlimit.ToDouble();
            entity.approvaluser_mid = request.approvaluser.ToInt();
            entity.sku_limit = request.sku_limit.ToInt();
            _projectSparepartRepository.Update(entity);
            if (_unitOfWork.Commit() < 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
            return new ObjectResult(CommonEnum.Succefull);
        }

        [HttpPost]
        public IActionResult DeleteSparepart(int id)
        {
            var entity = _projectSparepartRepository.Get(q => q.id == id && q.status == (int)RowState.Valid && q.projectid == ProjectId);
            if (entity == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            //设备结构树验证
            var attribution = _attributionRepository.Get(q =>
                q.sparepart_id == id && q.status == (int) RowState.Valid && q.projectid == ProjectId);
            if (attribution != null)
            {
                throw new BadRequestException(RequestEnum.SparepartCannotDelete);
            }

            entity.status = (int) RowState.Invalid;
            _projectSparepartRepository.Update(entity);

            //删除设备关联
            var entities = _sparepartMachineRepository.GetList(q => q.sparepartid == id && q.status == (int) RowState.Valid && q.projectid == ProjectId);
            foreach (var projectSparepartMachine in entities)
            {
                projectSparepartMachine.status = (int)RowState.Invalid;
                _sparepartMachineRepository.Update(projectSparepartMachine);
            }
            
            if (_unitOfWork.Commit() < 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
            return new ObjectResult(CommonEnum.Succefull);
        }

        [HttpPost]
        public IActionResult DeleteSpareparts([FromBody] RequestDeleteEntities request)
        {
            if (request.ids == null || !request.ids.Any())
            {
                throw new BadRequestException(RequestEnum.ParameterError);
            }
            foreach (var id in request.ids)
            {
                var entity = _projectSparepartRepository.Get(q => q.id == id && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                if (entity == null)
                {
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }

                entity.status = (int)RowState.Invalid;
                _projectSparepartRepository.Update(entity);

                //删除设备关联
                var entities = _sparepartMachineRepository.GetList(q => q.sparepartid == id && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                foreach (var projectSparepartMachine in entities)
                {
                    projectSparepartMachine.status = (int)RowState.Invalid;
                    _sparepartMachineRepository.Update(projectSparepartMachine);
                }
            }
           
            if (_unitOfWork.Commit() < 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
            return new ObjectResult(CommonEnum.Succefull);
        }

        [HttpGet]
        public IActionResult GetSparepartList(string keyword)
        {
            var entities =
                _projectSparepartRepository.GetList(q =>
                        q.projectid == ProjectId && q.status == (int) RowState.Valid && q.projectid == ProjectId)
                    .Where(t => t.sku > 0);
            if (!string.IsNullOrWhiteSpace(keyword))
            {
                entities = entities.Where(q =>
                    (q.title.Contains(keyword) || q.code.Contains(keyword) || q.remark.Contains(keyword) ||
                     q.param.Contains(keyword)));
            }
           
            return new ObjectResult(entities.ToList());
        }

        [HttpGet]
        public IActionResult ExportSparepartList(string machinetype1, string machinetype2, string keyword,
            string s_is_standard, string s_is_substitute, string s_report, int lastCheckValsparepart,
            string lastCheckVal, string charger)
        {

            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);

            var response = new List<ResponseGetSparepart>();
            var lastCheckList = new List<int>();
            if (!string.IsNullOrWhiteSpace(lastCheckVal))
            {
                foreach (var check in lastCheckVal.Split(','))
                {
                    lastCheckList.Add(int.Parse(check));
                }
            }

            var list = _projectSparepartRepository.GetPagedList(machinetype1.ToInt(), machinetype2.ToInt(), keyword, s_is_standard, s_is_substitute,
                s_report, lastCheckValsparepart, lastCheckList, charger.ToInt(), ProjectId, 1, 10, paged: false);
            if (!list.Data.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
           
            foreach (var sparepart in list.Data)
            {
                var stockStatus = 1; //正常
                //库存是否报警
                if (sparepart.purchase_status == 1)
                {
                    stockStatus = 3; //采购中
                }
                else if (sparepart.sku < sparepart.mini_sku) //报警
                {
                    stockStatus = 2;
                }

                var data = Mapper<ResponseGetSparepart, ResponseGetSparepart>.Map(sparepart);
                data.stock_status = stockStatus;
                //领用状态
                var result = GetSparepartInOut(sparepart.id);
                data.thisMonth_in = result[0];
                data.thisMonth_out = result[1];
                data.lastMonth_out = result[2];
                if (data.thisMonth_out > data.lastMonth_out)
                {
                    data.out_status = 1; //领用异常报警
                }
                response.Add(data);
            }
            var temporaryFileName = $"sparepart_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<SparepartList>();
            try
            {
                var repairList = new List<SparepartList>();
                var translateHelper = new TranslateHelper(_projectSparepartRepository.GetProjectLanguage(ProjectId) == (int)LanguageType.EN);
                foreach (var record in response)
                {
                    var entity = new SparepartList
                    {
                        Name = record.title,
                        Code = record.code,
                        Brand = record.brand,
                        Param = record.param,
                        IsExchange =
                            record.is_substitute == 1
                                ? translateHelper.GetTranslateText(TranslateEnEnum.Yes)
                                : translateHelper.GetTranslateText(TranslateEnEnum.No),
                        Sku = record.sku,
                        Location = record.warehouse,
                        Status = record.stock_status == 1
                            ? translateHelper.GetTranslateText(TranslateEnEnum.Normal)
                            : translateHelper.GetTranslateText(TranslateEnEnum.InventoryAlarm),
                        CurrentMonth = record.thisMonth_in,
                        CurrentUse = record.lastMonth_out,
                        LastMonth = record.thisMonth_out,
                        Alarm = record.out_status == 1
                            ? translateHelper.GetTranslateText(TranslateEnEnum.CollarAlarm)
                            : translateHelper.GetTranslateText(TranslateEnEnum.Normal),
                        Category = record.typeTitle,
                        MinKu = record.mini_sku,
                        MaxKu = record.max_sku
                    };
                    repairList.Add(entity);
                }

                helper.GenerateExcel(repairList, fileName);
                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Export sparepart failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }

        private List<int> GetSparepartInOut(int id)
        {
            var result = new List<int>();
            //月份信息
            var thisMonthBegin = UnixTimeHelper.GetUnixByDate(DateTime.Now.ToString(ParameterConstant.MouthFirstDay));
            var thisMonthEnd = UnixTimeHelper.GetUnixByDate(DateTime.Now.AddMonths(1).ToString(ParameterConstant.MouthFirstDay));
            var lastMonthBegin = UnixTimeHelper.GetUnixByDate(DateTime.Now.AddMonths(-1).ToString(ParameterConstant.MouthFirstDay));

            //领用状态
            result.Add(GetSparepartCount(id, thisMonthBegin, thisMonthEnd, (int)StockCategory.InStock)); // 本月收入
            result.Add(GetSparepartCount(id, thisMonthBegin, thisMonthEnd, (int)StockCategory.OutStock)); //本月领用
            result.Add(GetSparepartCount(id, lastMonthBegin, thisMonthBegin, (int)StockCategory.OutStock)); //上月领用

            return result;
        }

        [HttpGet]
        public IActionResult GetAlarmSpareparts()
        {
            var spars = _projectSparepartRepository.GetAlarmSpareparts(ProjectId);

            return new ObjectResult(spars);
        }
    }
}