using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Filters;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Request;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Response;
using Siger.Middlelayer.Common.Extensions;

namespace Siger.ApiACC.Controllers
{
    public class TraceController : BaseController
    {
        private readonly ISigerAccTraceRepository _sigerAccTrace;
        private readonly ISigerTrSnTraceRepository _trSnTrace;
        private readonly ISigerTrSnTraceDetailsRepository _sigerTrSnTraceDetails;
        private readonly ISigerRoutingOutStation _sigerRoutingOutStation;
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerProjectUserRepository _projectUser;
        private readonly IInspectStandardRepository _inspectStandardRepository;
        private readonly ISigerRoutingEventNo _routingEventNo;
        private readonly ISigerTrPowerSectionRepository _powerSection;
        private readonly ISnListRepository _snList;
        private readonly ISigerRoutingInStation _sigerRoutingInStation;
        private readonly ITrParameterConfigRepository _trParameterConfig;
        private readonly ISigerProjectLevelSectionRepository _levelSection;
        private readonly IProductPlanDetails _productPlanDetails;
        private readonly ISigerProjectLevelSectionMachineRepository _sigerProjectLevelSectionMachine;
        public TraceController(ISigerAccTraceRepository sigerAccTrace, ISigerRoutingOutStation sigerRoutingOutStation, ISigerProjectLevelSectionMachineRepository sigerProjectLevelSectionMachine
            , IUnitOfWork unitOfWork, ISigerProjectUserRepository projectUser, IInspectStandardRepository inspectStandardRepository
            , ISigerRoutingEventNo routingEventNo, ISigerTrPowerSectionRepository powerSection, ISnListRepository snList, ISigerRoutingInStation sigerRoutingInStation, ITrParameterConfigRepository trParameterConfig
            , ISigerProjectLevelSectionRepository levelSection, ISigerTrSnTraceRepository trSnTrace, ISigerTrSnTraceDetailsRepository sigerTrSnTraceDetails,IProductPlanDetails planDetails)
        {
            _sigerAccTrace = sigerAccTrace;
            _sigerRoutingOutStation = sigerRoutingOutStation;
            _unitOfWork = unitOfWork;
            _projectUser = projectUser;
            _inspectStandardRepository = inspectStandardRepository;
            _routingEventNo = routingEventNo;
            _powerSection = powerSection;
            _snList = snList;
            _sigerRoutingInStation = sigerRoutingInStation;
            _trParameterConfig = trParameterConfig;
            _levelSection = levelSection;
            _trSnTrace = trSnTrace;
            _sigerTrSnTraceDetails = sigerTrSnTraceDetails;
            _productPlanDetails = planDetails;
            _sigerProjectLevelSectionMachine = sigerProjectLevelSectionMachine;
        }

        [HttpPost]
        public IActionResult SaveTrace([FromBody]RequestTrace trace)
        {
            //20181224 检查自定义功能
            var BaseItem = _sigerAccTrace.GetBaseSetting(trace.SectionId, ProjectId);
            var SeqID = Guid.NewGuid().ToString();
            var uid = _sigerAccTrace.GetCheckkInUser(trace.SectionId, ProjectId);
            if (trace.UserId != 0)
            {
                uid = trace.UserId;
            }
            var line = _sigerAccTrace.Getline(trace.SectionId, ProjectId);
            if (BaseItem != null)
            {
                #region 检查seq=2 是否需要检查SN
                var product = " ";
                if (BaseItem.TraceBaseItem.Trace.TrackNoSn)
                {
                    _sigerAccTrace.SaveTrace(new SigerTrSnTrace
                    {
                        UID = uid,
                        SeqID = SeqID,
                        SN = trace.SN,
                        ProductID = product,
                        Station = trace.SectionId,
                        Line = line,
                        Result = trace.Result,
                        projectId = ProjectId,
                        TransDateTime = DateTime.Now,
                        LastUpdateTime = DateTime.Now
                    });
                    //不用检查SN 
                    if (_unitOfWork.Commit() > 0)
                    {
                        return new ObjectResult(CommonEnum.Succefull);
                    }
                    else
                    {
                        return new ObjectResult(CommonEnum.Fail);
                    }

                }
                #endregion
            }
            SaveTraceData(trace, uid);
            return new ObjectResult(CommonEnum.Succefull);
        }
        [HttpPost]
        public IActionResult SaveTFTrace([FromBody]RequestTFSaveTrace trace)
        {
            SaveTraceData(trace, trace.uid);
            return new ObjectResult(CommonEnum.Succefull);
        }

        /// <summary>
        /// 保存Tr_SN_TraceDetails 记录
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult SaveTraceDetils([FromBody]RequestTraceDetails traceDetails)
        {
            _sigerAccTrace.SaveTraceDetails(new SigerTrSNTraceDetail
            {
                SeqID = traceDetails.SeqID,
                SN = traceDetails.SN,
                Item = traceDetails.Item,
                Item2 = traceDetails.Item,
                Item3 = traceDetails.Item,
                Value = traceDetails.Value,
                Result = traceDetails.Result,
                TransDateTime = traceDetails.TransDateTime,
                LastUpdateTime = DateTime.Now,
                projectId = ProjectId
            });
            if (_unitOfWork.Commit() > 0)

                return new ObjectResult(CommonEnum.Succefull);
            else
                throw new BadRequestException(CommonEnum.Fail);
        }

        private void SaveTraceData(RequestTrace trace, int uid)
        {
            // 检查SN
            var snlist = _sigerAccTrace.FindSn(trace.SN, ProjectId);
            if (snlist == null)
            {
                throw new BadRequestException(AccEnum.Busi_SN_Null);
            }
            #region  实体事务
            ////1.先保存Tr_Trace表 insert 
            _sigerAccTrace.SaveTrace(new SigerTrSnTrace
            {
                UID = uid,
                SeqID = trace.SeqID,
                SN = trace.SN,
                ProductID = snlist.ProductCode,
                Station = trace.SectionId,
                Result = trace.Result,
                TransDateTime = DateTime.Now,
                LastUpdateTime = DateTime.Now,
                projectId = ProjectId
            });
            ////2.再保存Tr_SN_list表 modify
            //=========================================
            int EvenNo = 0;
            if (trace.Result.ToUpper() == "OK")
                EvenNo = EvenNoEnum.OK.GetHashCode();
            else
                EvenNo = EvenNoEnum.NG.GetHashCode();
            //==========================================
            var outObj = _sigerRoutingOutStation.GetList(f => f.EventNo == EvenNo && f.Station == trace.SectionId && f.projectId == ProjectId && f.status != (int)RowState.Invalid).FirstOrDefault();
            if (outObj == null)
            {
                throw new BadRequestException(AccEnum.Busi_EventNo_Null);
            }
            snlist.ResultStatus = outObj.ResultStatus;

            _sigerAccTrace.UpdateSNList(snlist);
            if (_unitOfWork.Commit() == 0)
                throw new BadRequestException(AccEnum.Busi_SaveCommit);
            #endregion
        }
        /// <summary>
        /// 检查Sn信息
        /// </summary>
        /// <param name="requestSnData"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult CheckSn([FromBody]RequestSnData requestSnData)
        {
            var type = PowerType.Web;
            if (requestSnData.type != 0)
            {
                type = (PowerType)requestSnData.type;
            }
            var resp = new ResponseSnData();
            resp.IsPass = false;//默认都为未通过
            //默认情况返回OK结果
            resp.ResultValue = "OK";
            #region 非SN信息剔除
            //（工票）是否配置工艺路径
            var wo = _productPlanDetails.GetProductRoute(requestSnData.SN, ProjectId);
            if (wo != null)
            {
                resp.Section = wo.SectionId;
                resp.ProductRoute = wo.RouteId;
                resp.ProductRouteDesc = wo.RouteName;
                return new ObjectResult(resp);
            }
            //是否人员信息（包含IC卡信息）
            var userData = _projectUser.Get(f => f.status == (int)RowState.Valid && f.projectid.Equals(ProjectId) && (f.work_code == requestSnData.SN || f.rank == requestSnData.SN));
            if (userData != null)
            {
                resp.Uid = userData.mid;
                resp.UserName = userData.name;
                return new ObjectResult(resp);
            }
            //检查是否有该页面权限
            if (!_powerSection.CheckPowerBySection(requestSnData.SectionId, ProjectId, requestSnData.path, type))
            {
                throw new BadRequestException(AccEnum.CanNotUseThisProgram);
            }
            //是否设备
            var machineData = _sigerAccTrace.GetSectionDataByMachine(requestSnData.SN, ProjectId);
            if (machineData != null)
            {
                //检查是否允许切换
                if (!_powerSection.CheckPowerBySection(machineData.Section, ProjectId, requestSnData.path, type))
                {
                    throw new BadRequestException(AccEnum.CanNotUseThisProgram);
                }
                //算新工位产量
                machineData.OKCount = _sigerAccTrace.GetTraceCountByResult(ProjectId, requestSnData.Uid, machineData.Section, EvenNoEnum.OK);
                machineData.NGCount = _sigerAccTrace.GetTraceCountByResult(ProjectId, requestSnData.Uid, machineData.Section, EvenNoEnum.NG);
                return new ObjectResult(machineData);
            }

            var eventNo = _routingEventNo.Get(f => f.status == (int)RowState.Valid && f.projectId.Equals(ProjectId) && f.Descr.Equals("OK"));
            if (eventNo != null)
            {
                resp.EventNo = eventNo.EventNo;
            }
            //是否EventNo
            var eventData = _routingEventNo.Get(f => f.status == (int)RowState.Valid && f.projectId.Equals(ProjectId) && f.EventNo == requestSnData.SN.ToInt());
            if (eventData != null)
            {
                resp.EventNo = eventData.EventNo;
                resp.ResultValue = eventData.Descr;
                return new ObjectResult(resp);
            }
            //算产量
            resp.OKCount = _sigerAccTrace.GetTraceCountByResult(ProjectId, requestSnData.Uid, requestSnData.SectionId, EvenNoEnum.OK);
            resp.NGCount = _sigerAccTrace.GetTraceCountByResult(ProjectId, requestSnData.Uid, requestSnData.SectionId, EvenNoEnum.NG);

            if (string.IsNullOrEmpty(requestSnData.SN))
            {
                throw new BadRequestException(CommonEnum.NoData);
            }
            //是否NG
            if (requestSnData.SN.ToUpper().Equals("NG"))
            {
                var ngData = _routingEventNo.Get(f => f.status == (int)RowState.Valid && f.projectId.Equals(ProjectId) && f.Descr.ToUpper() == requestSnData.SN.ToUpper());
                if (ngData != null)
                {
                    resp.EventNo = ngData.EventNo;
                    resp.ResultValue = ngData.Descr;
                    return new ObjectResult(resp);
                }
                else
                {
                    resp.Error = "没有维护NG代码，请联系管理员！";
                    return new ObjectResult(resp);
                }
            }
            #endregion

            #region SN信息检查
            //功能开关检查
            var BaseItem = _sigerAccTrace.GetBaseSetting(requestSnData.SectionId, ProjectId);
            if (BaseItem != null)
            {
                if (BaseItem.TraceBaseItem.Trace.TrackNoSn)
                {
                    resp.IsPass = true;
                    return new ObjectResult(resp);
                }
            }
            //sn是否存在
            var snlist = _snList.GetDataBySn(requestSnData.SN, ProjectId).FirstOrDefault();
            if (snlist == null)
                throw new BadRequestException(AccEnum.Busi_SN_Null);
            //过站检查
            var station = _levelSection.Get(f => f.id == requestSnData.SectionId);
            if (station == null)
                throw new BadRequestException(AccEnum.Station_Null);
            var routeIn = _sigerRoutingInStation.Get(f =>
                f.Station == requestSnData.SectionId && f.ProductId == snlist.ProductCode && f.projectId == ProjectId && f.status == (int)RowState.Valid);
            if (routeIn == null)
            {
                resp.Error = string.Format($"没有维护工站:{station.title }进站路由");
                return new ObjectResult(resp);
            }
            if (routeIn.ResultStatus != snlist.ResultStatus)
            {
                var outResult = _sigerRoutingOutStation.Get(f => f.ResultStatus == snlist.ResultStatus && f.projectId == ProjectId && f.status == (int)RowState.Valid);
                if (outResult == null)
                {
                    resp.Error = string.Format($"没有维护工站:{station.title }出站路由");
                    return new ObjectResult(resp);
                }
                var evno = _routingEventNo.Get(f => f.EventNo == outResult.EventNo && f.projectId == ProjectId && f.status == (int)RowState.Valid);
                var lastStation = _levelSection.Get(f => f.id == outResult.Station);
                resp.Error += string.Format("最后更新工站:{0} 结果:{1} 产品编号{2}", lastStation == null ? outResult.Station.ToStr() : lastStation.title, evno.Descr, snlist.ProductCode);
                return new ObjectResult(resp);
            }
            #endregion
            resp.IsPass = true;
            return new ObjectResult(resp);
        }
        /// <summary>
        /// 获取Trace记录
        /// </summary>
        /// <param name="requestSnData"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetTraceData([FromBody]RequestSnData requestSnData)
        {
            var resp = new ResponseTrace();
            var tracemodle = _trSnTrace.GetList(f => f.Station.Equals(requestSnData.SectionId) && f.status == (int)RowState.Valid, "id").Take(5);
            tracemodle.ToList().ForEach(
                da =>
                {
                    resp.TraceData.Add(Mapper<SigerTrSnTrace, ResponseTraceData>.Map(da));
                }
                );
            //算产量
            resp.OKCount = _sigerAccTrace.GetTraceCountByResult(ProjectId, requestSnData.Uid, requestSnData.SectionId, EvenNoEnum.OK);
            resp.NGCount = _sigerAccTrace.GetTraceCountByResult(ProjectId, requestSnData.Uid, requestSnData.SectionId, EvenNoEnum.NG);
            return new ObjectResult(resp);
        }
        /// <summary>
        /// 获取产线工站信息
        /// </summary>
        /// <param name="section"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetLineStationData(int section)
        {
            var lineStationData = _sigerAccTrace.GetLineStationData(section, ProjectId);
            return new ObjectResult(lineStationData);
        }

        /// <summary>
        /// /SKF 过站信息 
        /// </summary>
        /// <param name="trace"></param>
        /// <returns></returns>
        [NoTokenValidateFilter]
        [HttpPost]
        public IActionResult Save([FromBody]RequestTraceDetailsList trace)
        {
            var snlist = _snList.Get(f => f.SN == trace.SN);
            var SeqID = Guid.NewGuid().ToString();
            _trSnTrace.Insert(new SigerTrSnTrace
            {
                SeqID=SeqID,
                projectId = trace.projectId,
                Line = 0,
                Station = trace.SectionID,
                Position = trace.SectionID,
                UID=0,
                TransDateTime=DateTime.Now,
                LastUpdateTime=DateTime.Now,
                ProductID=snlist!=null?snlist.ProductCode:"",
                ProductRoute=0,
                Result=trace.Result,
                SN=trace.SN,
                status=(int)RowState.Valid,
                WO=""
            }); 
            foreach(var d in trace.Details)
            {
                var oqcId = d.ItemId;
                if (oqcId == 0)
                {
                    var intandartItem = _inspectStandardRepository.Get(f => f.sectionid == trace.SectionID && f.item == d.Item);
                    oqcId = intandartItem != null ? intandartItem.id : 0;
                }
                _sigerTrSnTraceDetails.Insert(new SigerTrSNTraceDetail
                {
                    SeqID = SeqID,
                    TransDateTime = DateTime.Now,
                    LastUpdateTime = DateTime.Now,
                    projectId = trace.projectId,
                    Item = d.Item,
                    Item3 = oqcId.ToStr(),
                    Value = d.Value,
                    Result = d.Result,
                    SN = trace.SN,
                    status = (int)RowState.Valid
                });
            }
            if (_unitOfWork.Commit() > 0)
                return new ObjectResult(CommonEnum.Succefull);
            else
                throw new BadRequestException(CommonEnum.Fail);
        }

        /// <summary>
        /// SKF 过站明细
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetDetails(string guid)
        {
            var data = _sigerTrSnTraceDetails.GetList(f => f.projectId == ProjectId && f.SeqID == guid).ToList();
            foreach(var dts in data)
            {
                var param = _trParameterConfig.Get(f => f.projectId == ProjectId && f.name.Contains(dts.Item));
                dts.Remarks = param != null ? param.attribute:"";

            }
            return new ObjectResult(data);
        }
    }
}
