using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using NPOI.SS.Formula.Functions;
using Siger.ApiCommon.Result;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Log;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.ApiCommon.Filters;
namespace Siger.ApiACC.Controllers
{
    public class SnlistController : BaseController
    {
        private readonly ISnListRepository _snListRepository;
        private readonly IUnitOfWork _unitOfWork;
        private readonly IProductPlanRepository _productPlanRepository;
        private readonly ISeriNumCfg _seriNumCfg;
        private readonly ISigerProjectProductRepository _sigerProjectProduct;

        public SnlistController(ISnListRepository snListRepository, IUnitOfWork unitOfWork, IProductPlanRepository productPlanRepository,ISeriNumCfg seriNumCfg,ISigerProjectProductRepository sigerProjectProduct)
        {
            _snListRepository = snListRepository;
            _unitOfWork = unitOfWork;
            _productPlanRepository = productPlanRepository;
            _seriNumCfg = seriNumCfg;
            _sigerProjectProduct = sigerProjectProduct;
        }
        /// <summary>
        /// 流转卡打印
        /// </summary>
        /// <param name="productCode"></param>
        /// <param name="woType"></param>
        /// <param name="wo"></param>
        /// <param name="page"></param>
        /// <param name="pagesize"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Getlist(string productCode,string woType,string wo,int page,int pagesize)
        {

            var result = _snListRepository.GetFlowCards(ProjectId, productCode, woType, wo, page, pagesize);
            return new PagedObjectResult(result.Data, result.Total);
        }

        /// <summary>
        /// 根据订单生成 Sn 号码
        /// </summary>
        /// <param name="planId">工单ID</param>
        /// <param name="ruleType">1:SN 2:Box</param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult CreateSnByWo(int planId, int ruleType = 1)
        {
           
            var planObj = _productPlanRepository.Get(f => f.id == planId);
            if (planObj == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            if (planObj.install_count >= planObj.quantity)
            {
                throw new BadRequestException(AccEnum.AlreadyCreateSn);
            }
            if (planObj.quantity == 0)
            {
                throw new BadRequestException(AccEnum.CountZero);
            }
            var productObj = _sigerProjectProduct.Get(f => f.code == planObj.product_code);
            if (productObj==null)
            {
                throw new BadRequestException(AccEnum.ProductInfo_Record_Null);
            }
            var serialCfg = _seriNumCfg.GetList(f => f.projectId == ProjectId && f.ProductID == planObj.product_code && f.Rule==ruleType && f.status == (int)RowState.Valid).ToList();
            if (!serialCfg.Any())
            {
                throw new BadRequestException(AccEnum.SerinumCfgEmpty);
            }
            //根据订单数量 生成 SN二维码

            var snlist = new List<SigerTrSnList>();
            for (int i = 0; i < planObj.quantity - planObj.install_count; i++)
            {
                var sn = GetLabel(serialCfg);
                if (string.IsNullOrEmpty(sn))
                    continue;
                if (snlist.Exists(s => s.SN == sn))
                    continue;
                if (_snListRepository.IsExist(f=>f.SN==sn))
                    continue;
                snlist.Add(new SigerTrSnList
                {
                    SN=sn,
                    projectId=ProjectId,
                    ProductCode= productObj.code,
                    ProductId=productObj.id,
                    InputDateTime=DateTime.Now,
                    TransDateTime=DateTime.Now,
                    WO=planObj.code,
                    status=(int)RowState.Valid,
                    ResultStatus="",
                    PN="",
                    WoType="",
                    printCount =0
                });
            }
            if (snlist.Count==0)
            {
                throw new BadRequestException(AccEnum.SerinumFull);
            }
            planObj.install_count +=  snlist.Count;
            _productPlanRepository.Update(planObj);
            _snListRepository.Insert(snlist);

            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }
        /// <summary>
        /// 根据规则生成二维码
        /// </summary>
        /// <param name="seriCfg"></param>
        /// <returns></returns>
        private string GetLabel(List<SigerTrSerinumcfg> seriCfg)
        {
            var LableStr = string.Empty;
            try
            {
                var yearStep = DateTime.Now.Year.ToString().Substring(2, 2);
                var dayStep = DateTime.Now.DayOfYear;
                var normalDate = DateTime.Now.ToString("yyyyMMdd");
                foreach (var cfg in seriCfg.OrderBy(o => o.Seq))
                {
                    var type = (SeriNumCfg)cfg.ItemType;
                    switch (type)
                    {
                        case SeriNumCfg.NORMAL://占位
                            {
                                LableStr += cfg.ItemValue;
                                break;
                            }
                        case SeriNumCfg.DATE://时间
                            {
                                //YYDDD 
                                if (cfg.TypeFormat.ToUpper() == SeriNumDateFormat.YearDate)
                                {
                                    var key = yearStep + dayStep;
                                    if (dayStep.ToString().Length < 3)
                                    {
                                        var tempKey = string.Empty;
                                        for (int i = 0; i < 3 - dayStep.ToString().Length; i++)
                                        {
                                            tempKey += "0";
                                        }
                                        key = yearStep + tempKey + dayStep;
                                    }
                                    if (cfg.ItemValue != key)
                                    {
                                        cfg.ItemValue = key;
                                        _seriNumCfg.Update(cfg);
                                        if (_unitOfWork.Commit() == 0)
                                        {
                                            throw new BadRequestException(AccEnum.Busi_Create_Sn_Fail);
                                        }
                                        //重置流水号
                                        var serinum = seriCfg.Find(f => f.ProductID == cfg.ProductID && f.ItemType == (int)SeriNumCfg.SeriNum);
                                        if (serinum != null)
                                        {
                                            serinum.ItemValue = "0";
                                            _seriNumCfg.Update(serinum);
                                            if (_unitOfWork.Commit() == 0)
                                            {
                                                throw new BadRequestException(AccEnum.Busi_Create_Sn_Fail);
                                            }
                                        }
                                        else
                                        {
                                            throw new BadRequestException(AccEnum.Busi_Create_Sn_Fail);
                                        }
                                    }

                                    LableStr += key;
                                }

                                if (cfg.TypeFormat.ToUpper() == SeriNumDateFormat.YearMonthDate)
                                {
                                    if (normalDate != cfg.ItemValue)
                                    {
                                        cfg.ItemValue = normalDate;
                                        _seriNumCfg.Update(cfg);
                                        if (_unitOfWork.Commit() == 0)
                                        {
                                            throw new BadRequestException(AccEnum.Busi_Create_Sn_Fail);
                                        }
                                        //重置流水号
                                        var serinum = seriCfg.Find(f => f.ProductID == cfg.ProductID && f.ItemType == (int)SeriNumCfg.SeriNum);
                                        if (serinum != null)
                                        {
                                            serinum.ItemValue = "0";
                                            _seriNumCfg.Update(serinum);
                                            if (_unitOfWork.Commit() == 0)
                                            {
                                                throw new BadRequestException(AccEnum.Busi_Create_Sn_Fail);
                                            }
                                        }
                                        else
                                        {
                                            throw new BadRequestException(AccEnum.Busi_Create_Sn_Fail);
                                        }
                                    }
                                    LableStr = LableStr + normalDate;
                                }

                                break;
                            }
                        case SeriNumCfg.SeriNum://流水
                            {
                                var len = cfg.Length;
                                if(cfg.Length==0)
                                {
                                    len = 4;
                                }
                                var step = 1;
                                int.TryParse(cfg.ItemValue, out step);

                                step += 1;
                                cfg.ItemValue = step.ToString();
                                if (cfg.ItemValue.Length > len)
                                {
                                    throw new BadRequestException(AccEnum.Busi_Create_Sn_Fail);
                                }
                                _seriNumCfg.Update(cfg);
                                if (_unitOfWork.Commit() == 0)
                                {
                                    throw new BadRequestException(AccEnum.Busi_Create_Sn_Fail);
                                }
                                var fixedZero = string.Empty;
                                for (int i = 0; i < len - cfg.ItemValue.Length; i++)
                                {
                                    fixedZero += "0";
                                }
                                LableStr = LableStr + fixedZero + step;
                                break;
                            }
                        case SeriNumCfg.Replace://占位替换
                            {
                                //switch (cfg.ItemValue)
                                //{
                                //    case "P1":
                                //        {
                                //            if (!string.IsNullOrEmpty(buildObj.Replace1))
                                //                LableStr = LableStr + buildObj.Replace1;
                                //            break;
                                //        }
                                //}
                                break;
                            }
                        case SeriNumCfg.Code: //校验码
                            {
                                var code = ChekCode(LableStr);
                                LableStr += code.ToStr();
                                break;
                            }
                    }

                }
            }catch(Exception e)
            {
                Logger.WriteLineError(e.ToString());
            }
            return LableStr;
        }

        /// <summary>
        /// 东方富力校验码
        /// </summary>
        /// <returns></returns>
        private double ChekCode(string lable)
        {
            if (string.IsNullOrEmpty(lable))
            {
                return 0;
            }
            var charStr = lable.Trim();
            if (string.IsNullOrEmpty(charStr))
            {
                return 0;
            }
            var ret = 0d;
            var source = GetDic();
            var stepWeight = 0d;//权数 求和
            for(int i=0;i <charStr.Length;i ++)
            {
                //1.每个字符值 * 权数
                var str = charStr[i].ToStr();
                source.TryGetValue(str, out int val);
                stepWeight += (i + 1) * val;
            }
            //2.除以103
            var result = stepWeight % 103 ;
            //3.取各位数
            ret = result % 10;
            return ret;
        }
        /// <summary>
        /// 东方富力检验码规则
        /// </summary>
        /// <returns></returns>
        private Dictionary<string,int>GetDic()
        {
            var dic = new Dictionary<string, int> ();
            dic.Add("0",0);
            dic.Add("1", 1);
            dic.Add("2", 2);
            dic.Add("3", 3);
            dic.Add("4", 4);
            dic.Add("5", 5);
            dic.Add("6", 6);
            dic.Add("7", 7);
            dic.Add("8", 8);
            dic.Add("9", 9);
            dic.Add("A", 10);
            dic.Add("B", 11);
            dic.Add("C", 12);
            dic.Add("D", 13);
            dic.Add("E", 14);
            dic.Add("F", 15);
            dic.Add("G", 16);
            dic.Add("H", 17);
            dic.Add("J", 18);
            dic.Add("K", 19);
            dic.Add("L", 20);
            dic.Add("M", 21);
            dic.Add("N", 22);
            dic.Add("P", 23);
            dic.Add("R", 24);
            dic.Add("S", 25);
            dic.Add("T", 26);
            dic.Add("U", 27);
            dic.Add("V", 28);
            dic.Add("W", 29);
            dic.Add("X", 30);
            dic.Add("Y", 31);
            dic.Add("Z", 32);
            return dic;
        }

        /// <summary>
        /// 获取工单数量以及信息
        /// </summary>
        /// <param name="sn"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetWoInfo(string sn)
        {
            var snData = _snListRepository.Get(f => f.SN.Equals(sn) && f.projectId == ProjectId &&
                                                                            f.status == (int)RowState.Valid);
            if (snData == null)
            {
                throw new BadRequestException(AccEnum.Busi_SN_Null);
            }

            var woInfo = _snListRepository.GetWoInfo(sn, ProjectId);

            if(!woInfo.Any())
                throw new BadRequestException(CommonEnum.RecordNotFound);
            return new ObjectResult(woInfo.FirstOrDefault());
        }
    }
}
