using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Siger.DataSchedule.Infrastructure.Extend;
using Siger.Middlelayer.AccRepository;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Redis;
using Siger.Middlelayer.Redis.RedisEntities;
using Siger.Middlelayer.Repository.Entities;

namespace Siger.Schedule.AccModule
{
    public class AccCalculateTrace : IScheduleJob
    {
        AccCalculateTraceJob andonHelper;
        public void PreInit(ScheduleContext context)
        {
            Logger.RegisterLogEngine(Module.Acc);
            andonHelper = new AccCalculateTraceJob();
        }
        public void Execute(ScheduleContext context)
        {
            andonHelper.Execute();
        }


        public void AfterExecute(ScheduleContext context)
        {

        }


        public void Undo()
        {

        }
    }
    public class AccCalculateTraceJob
    {
        private static readonly ApiAccDbContext _context;

        static AccCalculateTraceJob()
        {
            _context = new ApiAccDbContext();
        }

        public void Execute()
        {
            try
            {
                _context.siger_tr_sn_trace_summary.ToList().ForEach(
                data =>
                {
                    _context.siger_tr_sn_trace_summary.Remove(data);
                });
                var dbConfigs = RedisCache.Instance.GetDbNameConfigs();
                var programList = new List<ProgramList>();
                //根据字典重summarytime确定是否计算产量
                var pidList = _context.siger_tr_dict.Where(f => f.cat == "summarytime" && f.status == (int)RowState.Valid).Select(s => s.projectId).Distinct().ToList();
                foreach (var pid in pidList)
                {

                    #region //获取时间
                    var sumtime = _context.siger_tr_dict.FirstOrDefault(f => f.cat == "summarytime" && f.status == (int)RowState.Valid && f.projectId == pid);
                    if (sumtime == null)
                    {
                        continue;
                    }
                    var nowtime = UnixTimeHelper.GetUnixByDate(DateTime.Now.ToString());
                    var settime = UnixTimeHelper.GetUnixByDate(DateTime.Now.ToString(ParameterConstant.DateFormat) + " " + sumtime.dval);
                    if (nowtime < settime)
                    {
                        settime = UnixTimeHelper.GetUnixByDate(DateTime.Now.AddDays(-1).ToString(ParameterConstant.DateFormat) + " " + sumtime.dval);
                    }
                    if (settime == 0)
                    {
                        Logger.WriteLineError($"ProjectId:{pid}的summarytime转化失败 请确定格式为:08:00:00");
                        continue;
                    }
                    var start = UnixTimeHelper.ConvertStringDateTime(settime.ToString());
                    var end = UnixTimeHelper.ConvertStringDateTime(nowtime.ToString());
                    var unixstart = settime;
                    var unixend = nowtime;
                    #endregion
                    #region//获取最后一道工艺
                    var lastprocess = from spp in _context.siger_project_process
                                      where spp.status == (int)RowState.Valid && spp.ProjectId.Equals(pid)
                                      group spp by new { spp.Product_code, spp.Process_Type } into temp
                                      let max = temp.OrderByDescending(o => o.Process_Seq).FirstOrDefault().Process_Seq
                                      let key = temp.Key
                                      select new siger_project_process { Product_code = key.Product_code, Process_Type = key.Process_Type, Process_Seq = temp.Max(f => f.Process_Seq) };

                    var processData = (from s in lastprocess
                                       join t in _context.siger_project_process on new { code = s.Product_code, seq = s.Process_Seq, type = s.Process_Type, status = (int)RowState.Valid }
                                       equals new { code = t.Product_code, seq = t.Process_Seq, type = t.Process_Type, status = t.status }
                                       select t.id).ToList();
                    #endregion

                    //var basketModel = _context.siger_tr_product_report.Where(f => f.status == (int)RowState.Valid && f.Time >= start && f.Time <= end & f.projectId.Equals(pid)).ToList();
                    var productReportModel = _context.siger_project_product_report.Where(f => f.status == (int)RowState.Valid && f.time >= unixstart && f.time <= unixend & f.projectid.Equals(pid)).ToList();
                    var traceModel = _context.siger_tr_sn_trace.Where(f => f.status == (int)RowState.Valid && f.TransDateTime >= start && f.TransDateTime <= end & f.projectId.Equals(pid)).ToList();
                    IFormatProvider ifp = new CultureInfo("zh-CN", true);
                    var _busidateFormat = DateTime.Now.ToString("yyyyMMdd");
                    var busidate = DateTime.ParseExact(_busidateFormat, "yyyyMMdd", ifp);
                    var basketttlModel = _context.siger_tr_basket_report_ttl.Where(f => f.status == (int)RowState.Valid && f.BusiDate ==Convert.ToDateTime(busidate)  & f.projectId.Equals(pid)).ToList();
                    var stations = GetStations(pid);
                    foreach (var station in stations)
                    {
                        //当前工位不计入产量的product
                        var products = from st in _context.siger_tr_routing_instation
                                           //join ou in _context.siger_tr_routing_outstation
                                           //on new { result = st.ResultStatus, status = (int)RowState.Valid } equals new { result = ou.ResultStatus, status = ou.status }
                                       where processData.Contains(st.ProcessId) && st.status == (int)RowState.Valid && st.Station.Equals(station.id)
                                       select st.ProductId;

                        //取出当前工位最后一笔Trace的id
                        var ids = traceModel.Where(f => f.Station.Equals(station.id)).GroupBy(g => g.SN).Select(s => s.Max(m => m.id));
                        var nowTrace = traceModel.Where(f => ids.Contains(f.id));
                        #region //计算数量
                        var ngCount = 0;
                        var okCount = 0;
                        var qty = 0;
                        var workcount = 0;
                        //批次追溯
                        foreach (var data in basketttlModel.Where(f => f.Position.Equals(station.id)))
                        {
                            ngCount += data.NgCount + data.NgCount2;
                            okCount += data.OkCount;
                            qty += data.NgCount + data.NgCount2 + data.OkCount;
                            if (!products.Contains(data.ProductBh))
                            {
                                workcount += data.OkCount;
                            }
                        }
                        //精确追溯
                        qty += nowTrace.Where(f => f.Station.Equals(station.id)).Select(s => s.SN).Distinct().Count();
                        ngCount += nowTrace.Where(f => f.Station.Equals(station.id) && !f.Result.Equals(EvenNoEnum.OK.ToString(), StringComparison.OrdinalIgnoreCase)).Select(s => s.SN).Distinct().Count();
                        okCount += nowTrace.Where(f => f.Station.Equals(station.id) && f.Result.Equals(EvenNoEnum.OK.ToString(), StringComparison.OrdinalIgnoreCase)).Select(s => s.SN).Distinct().Count();
                        workcount += nowTrace.Where(f => f.Station.Equals(station.id) && f.Result.Equals(EvenNoEnum.OK.ToString(), StringComparison.OrdinalIgnoreCase) && !products.Contains(f.ProductID)).Select(s => s.SN).Distinct().Count();
                        //报工数
                        foreach (var data in productReportModel.Where(f => f.station.Equals(station.id)))
                        {
                            ngCount += data.nok_number;
                            okCount += data.actual_output;
                            qty += data.output;
                        }
                        #endregion

                        // 插入SigerTrSnTraceSummary
                        var model = new SigerTrSnTraceSummary
                        {
                            Line = station.parentid,
                            Station = station.id,
                            TransDatetime = DateTime.Now,
                            projectId = pid,
                            NgCount = ngCount,
                            OkCount = okCount,
                            Quantity = qty,
                            WorkCount = workcount,
                        };
                        _context.siger_tr_sn_trace_summary.Add(model);
                    }
                }
                _context.SaveChanges();
            }
            catch (Exception ex)
            {
                Logger.WriteLineError(ex.Message);
            }
        }
        /// <summary>
        /// 获取产线最后一层
        /// </summary>
        /// <param name="pid"></param>
        /// <returns></returns>
        private List<siger_project_level_section> GetStations(int pid)
        {
            var linelevel = _context.siger_project_level.Where(f => f.projectid == pid).OrderByDescending(o => o.id).ToList();
            if (!linelevel.Any() || linelevel.Count < 2)
                return new List<siger_project_level_section>();
            var stationSetion = _context.siger_project_level_section.Where(f => f.projectid == pid && f.levelid == linelevel[0].id);
            return stationSetion.ToList();
        }
    }
}
