using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.Log;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Entities;

namespace Siger.Middlelayer.AccRepository.Repositories
{
    internal class SigerAccTraceRepository : AccRepositoryBase<SigerTrSNTraceDetail>, ISigerAccTraceRepository
    {
        private ApiAccDbContext accDbContext;
        private IUnitOfWork _unitOfWork;

        public SigerAccTraceRepository(ApiAccDbContext context, IUnitOfWork unitOfWork) : base(context)
        {
            accDbContext = context;
            _unitOfWork = unitOfWork;
        }

        /// <summary>
        /// 获取 站别功能配置
        /// </summary>
        /// <param name="sectionId"></param>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public ResponeBaseItem GetBaseSetting(int sectionId, int projectId)
        {
            var Ret = new ResponeBaseItem();
            Ret.PackingBaseItem = new PackingBaseItem
            {
                Packing = new PackingItems()
            };
            Ret.TraceBaseItem = new TraceBaseItem
            {
                Trace = new TraceItems()
            };
            Ret.Line = Getline(sectionId, projectId);
            Ret.Station = sectionId;
            var BaseItemObj = accDbContext.siger_tr_station_base_setting.Where(f => f.Station == sectionId && f.status == (int)RowState.Valid);
            if (!BaseItemObj.Any())
                return Ret;
            foreach (var obj in BaseItemObj)
            {
                if (obj.GroupName.Trim() == BaseItem.TraceCheck)
                {
                    Ret.TraceBaseItem.GroupName = obj.GroupName;
                    switch ((BaseSettingEnum)obj.Seq)
                    {
                        case BaseSettingEnum.TrackMachine://启用机加工
                            Ret.TraceBaseItem.Trace.TrackMachine = true;
                            break;
                        case BaseSettingEnum.TrackNoSn:// 保存追溯 不检查SN 不检查过站信息
                            Ret.TraceBaseItem.Trace.TrackNoSn = true;
                            break;
                        case BaseSettingEnum.TraceMongoDBSN:
                            Ret.TraceBaseItem.Trace.TraceMongoDBSN = true;
                            break;
                        case BaseSettingEnum.SaveCoarse:
                            Ret.TraceBaseItem.Trace.SaveCoarse = true;
                            break;
                        case BaseSettingEnum.SaveVSN:
                            Ret.TraceBaseItem.Trace.SaveVSN = true;
                            break;
                        case BaseSettingEnum.NoCollectionMachineState:
                            Ret.TraceBaseItem.Trace.NoCollectionMachineState = true;
                            break;
                        case BaseSettingEnum.SaveResultCreateSn:
                            Ret.TraceBaseItem.Trace.SaveResultCreateSn = true;
                            break;
                        case BaseSettingEnum.UseCoarseLifeCreaetSn:
                            Ret.TraceBaseItem.Trace.UseCoarseLifeCreaetSn = true;
                            break;
                        case BaseSettingEnum.NotAllowDebugSn:
                            Ret.TraceBaseItem.Trace.NotAllowDebugSn = true;
                            break;
                        case BaseSettingEnum.CreateSNbeforeSaveTrace:
                            Ret.TraceBaseItem.Trace.CreateSNbeforeSaveTrace = true;
                            break;
                        case BaseSettingEnum.ClearDataCollection:
                            Ret.TraceBaseItem.Trace.ClearDataCollection = true;
                            break;
                        case BaseSettingEnum.GetSectionID:
                            Ret.TraceBaseItem.Trace.GetSectionID = true;
                            break;
                        case BaseSettingEnum.TrackNoFirstCheck:
                            Ret.TraceBaseItem.Trace.TrackNoFirstCheck = true;
                            break;
                        default:
                            break;
                    }
                }
                if (obj.GroupName.Trim() == BaseItem.PackingCheck)
                {
                    Ret.PackingBaseItem.GroupName = obj.GroupName;
                    switch (obj.Seq)
                    {
                        case 1://启用机加工
                            Ret.PackingBaseItem.Packing.Packing_NoCheckSn = true;
                            break;
                        default:
                            break;
                    }
                }
            }
            return Ret;
        }

        public int GetCheckkInUser(int sectionId, int projectId)
        {
            var ChkInEmp = accDbContext.siger_tr_employ_station.Where(f => f.Station == sectionId && f.projectId == projectId && f.status != (int)RowState.Invalid);
            if (ChkInEmp.Any())
            {
                var lEmp = ChkInEmp.OrderByDescending(o => o.LastUpdate).FirstOrDefault();
                return lEmp.UserID;
            }
            return -1;
        }
        /// <summary>
        /// 查找追溯主表最后一次SN
        /// </summary>
        /// <param name="projectid"></param>
        /// <param name="station"></param>
        /// <param name="sn"></param>
        /// <returns></returns>
        public SigerTrSnTrace FindSeq(int projectid, int station, string sn)
        {
            var line = Getline(station, projectid);
            return accDbContext.siger_tr_sn_trace.Where(f => f.Station != station && f.Line == line && f.SN == sn && f.status != (int)RowState.Invalid).OrderByDescending(s => s.TransDateTime).FirstOrDefault();
        }
       
        /// <summary>
        /// 保存追溯明细
        /// </summary>
        /// <param name="traceDetails">明细实体对象</param>
        /// <returns></returns>
        public void SaveTraceDetails(SigerTrSNTraceDetail traceDetails)
        {
            accDbContext.siger_tr_sn_trace_detail.Add(traceDetails);
        }
        /// <summary>
        /// 保存追溯主表
        /// </summary>
        /// <param name="sigerTrSnTrace">明细实体对象</param>
        /// <returns></returns>
        public void SaveTrace(SigerTrSnTrace sigerTrSnTrace)
        {
            accDbContext.siger_tr_sn_trace.Add(sigerTrSnTrace);
        }
        /// <summary>
        /// 更改SN的ResultStatus
        /// </summary>
        /// <param name="sn">sn必须为有效值</param>
        /// <param name="station">station必须为有效值</param>
        /// <param name="uid"></param>
        /// <param name="resultstatus"></param>
        /// <param name="eventNo"></param>
        public string SaveTraceAndUpdateStatus(string sn, int station, int uid, string resultstatus, EvenNoEnum eventNo = EvenNoEnum.OK)
        {
            //station必须存在
            var pid = accDbContext.siger_project_level_section.Where(f => f.id == station).FirstOrDefault();
            var snData = accDbContext.siger_tr_sn_list.Where(f => f.SN == sn && f.projectId == pid.projectid).FirstOrDefault();
            var line = pid.parentid;
            //update sn status
            if (snData.ResultStatus != resultstatus)
            {
                snData.ResultStatus = resultstatus;
                snData.TransDateTime = DateTime.Now;
                accDbContext.siger_tr_sn_list.Update(snData);
            }
            //save tr_sn_trace
            var trace = new SigerTrSnTrace
            {
                //SeqID = IdHelper.GenerateSeqId<string>(),
                SeqID = System.Guid.NewGuid().ToString(),
                Line = line,
                Result = eventNo.ToString(),
                SN = sn,
                Station = station,
                LastUpdateTime = DateTime.Now,
                TransDateTime = DateTime.Now,
                ProductID = snData.ProductCode,
                UID = uid,
                WO = snData.WO,
                projectId = snData.projectId
            };
            accDbContext.siger_tr_sn_trace.Add(trace);
            return trace.SeqID;
        }
        public void SaveSnlist(SigerTrSnList snlistObj)
        {
            accDbContext.siger_tr_sn_list.Add(snlistObj);
        }
        public void UpdateSNList(SigerTrSnList sigerTrSnList)
        {
            accDbContext.siger_tr_sn_list.Update(sigerTrSnList);
        }
        /// <summary>
        /// 检查SN
        /// </summary>
        /// <param name="Sn"></param>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public SigerTrSnList FindSn(string Sn, int projectId)
        {
            var result = accDbContext.siger_tr_sn_list.FirstOrDefault(f => f.SN == Sn && f.projectId == projectId && f.status != (int)RowState.Invalid);
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="section"></param>
        /// <param name="projectid"></param>
        /// <returns>0:false </returns>
        public int Getline(int section, int projectid)
        {
            var levelObj = GetLevel_Section(section, projectid);
            if (levelObj == null)
                return 0;
            else
                return levelObj.parentid;
        }
        public SigerTrClearData FindClearData(int line, int projectid)
        {
            return accDbContext.siger_tr_clear_data.Where(f => f.Line == line && f.status != (int)RowState.Invalid && f.projectId == projectid)
                .OrderByDescending(o => o.Time).FirstOrDefault();
        }
        public ResponseSnData GetSectionDataByMachine(string code, int pid)
        {
            var resp = new ResponseSnData();
            var query = from spm in accDbContext.siger_project_machine
                        join splsm in accDbContext.siger_project_machine_attribution on spm.id equals splsm.machine
                        where spm.code.Equals(code) && spm.status == (int)RowState.Valid && spm.projectid.Equals(pid)
                        select splsm.station;
            var section = query.FirstOrDefault();
            if (section == 0)
            {
                return null;
            }
            resp.Section = section;
            var sectionValue = string.Empty;
            var sectionModle = accDbContext.siger_project_level_section.Where(f => f.status == (int)RowState.Valid && f.projectid == pid).ToList();
            while (true)
            {
                var sectionData = BuildSectionData(section, pid, sectionModle);
                if (sectionData == null)
                {
                    resp.SectionValue = sectionValue;
                    return resp;
                }
                sectionValue = sectionData.title + "->" + sectionValue;
                section = sectionData.parentid;
            }
        }
        /// <summary>
        /// 获取产线->工位信息
        /// </summary>
        /// <param name="section"></param>
        /// <param name="pid"></param>
        /// <returns></returns>
        public string GetLineStationData(int section, int pid)
        {
            var resp = string.Empty;
            var sectionModle = accDbContext.siger_project_level_section.Where(f => f.status == (int)RowState.Valid && f.projectid == pid).ToList();
            while (true)
            {
                var sectionData = BuildSectionData(section, pid, sectionModle);
                if (sectionData == null)
                {
                    return resp;
                }
                resp = sectionData.title + "->" + resp;
                section = sectionData.parentid;
            }
        }
        /// <summary>
        /// 获取Section信息
        /// </summary>
        /// <param name="section"></param>
        /// <param name="pid"></param>
        /// <param name="sectionModle"></param>
        /// <returns></returns>
        private siger_project_level_section BuildSectionData(int section, int pid, List<siger_project_level_section> sectionModle)
        {
            var data = sectionModle.Where(f => f.status == (int)RowState.Valid && f.projectid == pid && f.id == section).FirstOrDefault();
            if (data == null)
            {
                return null;
            }
            return data;
        }
        /// <summary>
        /// 计算当班产量
        /// </summary>
        /// <param name="pid"></param>
        /// <param name="uid"></param>
        /// <param name="section"></param>
        /// <param name="results"></param>
        /// <returns></returns>
        public int GetTraceCountByResult(int pid, int uid, int section, EvenNoEnum results)
        {
            Expression<Func<SigerTrSnTrace, bool>> funResult = f => true;
            switch (results)
            {
                case EvenNoEnum.OK:
                    funResult = f => f.Result.Equals(EvenNoEnum.OK.ToString());
                    break;
                case EvenNoEnum.NG:
                    funResult = f => !f.Result.Equals(EvenNoEnum.OK.ToString());
                    break;
            }
            var usermodle = accDbContext.siger_project_user.Where(f => f.status == (int)RowState.Valid && f.mid == (uid)).FirstOrDefault();
            if (usermodle == null)
            {
                Logger.WriteLineInfo($"GetOkCount:uid:{uid}人员信息未找到");
                return 0;
            }
            var shiftmodle = accDbContext.siger_project_shift.Where(f => f.status == (int)RowState.Valid && f.sectionid.Equals(usermodle.sectionid)).ToList();
            if (!shiftmodle.Any())
            {
                Logger.WriteLineInfo($"GetOkCount:sectionid:{usermodle.sectionid}排班信息未找到");
                return 0;
            }
            var nowtime = UnixTimeHelper.GetUnixTime(DateTime.Now.ToString("HH:mm"));
            var starttime = DateTime.Now.ToString(ParameterConstant.DateFormat) + " ";
            var endtime = DateTime.Now.ToString(ParameterConstant.DateFormat) + " ";
            foreach (var item in shiftmodle)
            {
                if (nowtime >= item.start_time && nowtime < item.end_time)
                {
                    endtime += UnixTimeHelper.GetTimeByUnix(item.end_time);
                    starttime += UnixTimeHelper.GetTimeByUnix(item.start_time);
                }
            }
            if (DateTime.TryParse(starttime, out DateTime start) && DateTime.TryParse(endtime, out DateTime end))
            {
                var traceModle = accDbContext.siger_tr_sn_trace.Where(f => f.Station.Equals(section) && f.status == (int)RowState.Valid && f.TransDateTime >= start && f.TransDateTime < end);
                return traceModle.Count(funResult);
            }
            return 0;
        }

    }
}
