using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Result;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Response;
using Siger.Middlelayer.AccRepository.Request;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Extensions;
using System.Linq;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;
using Siger.Middlelayer.Utility.Helpers;
using System.IO;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Share.Enum.ModuleEnum;

namespace Siger.ApiACC.Controllers
{
    public class QmsCheckController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IAutomationFixtureToolsProductRepository _automationFixtureToolsProduct;
        private readonly ISigerProjectProductRepository _productRepository;
        private readonly ISigerProjectLevelRepository _levelRepository;
        private readonly ISigerProjectLevelSectionRepository _levelSectionRepository;
        private readonly IInspectStandardRepository _inspectStandard;
        private readonly ICheckSnTraceInspectionRepository _traceInspectionRepository;
        private readonly ICheckSnTraceDetailRepository _traceDetailRepository;
        private readonly ICheckSnListRepository _snListRepository;
        private readonly ISigerTrMaterialsRepository _materialsRepository;
        private readonly IAutomationTaskListRepository _automationTaskList;
        private readonly IAutomationFixtureMonitor _fixtureMonitor;

        public QmsCheckController(IUnitOfWork unitOfWork, IAutomationFixtureToolsProductRepository automationFixtureToolsProduct,
            ISigerProjectProductRepository productRepository, ISigerProjectLevelRepository levelRepository,
            ISigerProjectLevelSectionRepository levelSectionRepository, IInspectStandardRepository inspectStandard,
            ICheckSnTraceInspectionRepository traceInspectionRepository, ICheckSnTraceDetailRepository traceDetailRepository,
            ICheckSnListRepository checkSnListRepository, ISigerTrMaterialsRepository materialsRepository,
            IAutomationTaskListRepository automationTaskListRepository, IAutomationFixtureMonitor fixtureMonitor)
        {
            _unitOfWork = unitOfWork;
            _automationFixtureToolsProduct = automationFixtureToolsProduct;
            _productRepository = productRepository;
            _levelRepository = levelRepository;
            _levelSectionRepository = levelSectionRepository;
            _inspectStandard = inspectStandard;
            _traceInspectionRepository = traceInspectionRepository;
            _traceDetailRepository = traceDetailRepository;
            _snListRepository = checkSnListRepository;
            _materialsRepository = materialsRepository;
            _automationTaskList = automationTaskListRepository;
            _fixtureMonitor = fixtureMonitor;
        }
        [HttpPost]
        public IActionResult AddManual([FromBody]RequestAddDataCollection req)
        {
            var product = _productRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                t.id == req.productid);
            if (product == null)
            {
                throw new BadRequestException(RequestEnum.ProductNotFound);
            }
            var maxLevel = _levelRepository.GetList(t => t.status == (int)RowState.Valid && t.projectid == ProjectId).Max(q => q.id);
            var section = _levelSectionRepository.Get(t => t.status == (int)RowState.Valid && t.projectid == ProjectId && t.id == req.sectionid);
            if (section == null || section.levelid != maxLevel)
            {
                throw new ServerException(1052);
            }
            var machine = _inspectStandard.GetMachineBySectionId(section.id, ProjectId);

            if (string.IsNullOrEmpty(req.result))
            {
                throw new BadRequestException(RequestEnum.SelectCheckResult);
            }

            if(req.result == ((int)SendTestType.DeviationRelease).ToString() && (string.IsNullOrEmpty(req.quantity) || req.quantity.ToInt() < 1))
            {
                throw new BadRequestException(RequestEnum.DeviationReleaseQuantityNotNull);
            }

            var items = _inspectStandard.GetList(t => req.details.Select(q => q.itemid).Contains(t.id)).ToList();
            var indexs = req.details.Select(t => t.index).Distinct().ToList();
            foreach (var index in indexs)//验证传入参数
            {
                var traceDetails = req.details.Where(t => t.index == index).OrderBy(t => t.index).ToList();
                if (traceDetails.Any())
                {
                    foreach (var detail in traceDetails)
                    {
                        var item = items.FirstOrDefault(t => t.id == detail.itemid);
                        if (item == null)
                        {
                            throw new BadRequestException(RequestEnum.ParameterMiss);
                        }
                        if (item.value_category == (int)ValueCategory.Maxmin && (detail.lowerlimit.HasValue &&
                                !detail.upperlimit.HasValue || detail.upperlimit.HasValue && !detail.lowerlimit.HasValue ||
                                (detail.upperlimit.HasValue && detail.lowerlimit.HasValue && detail.upperlimit.Value < detail.lowerlimit.Value)))
                        {
                            throw new BadRequestException(RequestEnum.MaxMinError);
                        }
                    }
                }
            }

            var traceResult = "";//检验结果可以传OK,2,NG,也可以传1,2,3
            if (req.result.ToUpper() == "OK" || req.result.ToUpper() == "NG")
            {
                traceResult = req.result.ToUpper();
            }
            else
            {
                if (req.result.ToInt() == (int)SendTestType.Qalified || req.result.ToInt() == (int)SendTestType.DeviationRelease)
                {
                    traceResult = "OK";
                }
                else
                {
                    traceResult = "NG";
                }
            }
            
            var insertDetailList = new List<SnTraceDetailList>();
            foreach (var index in indexs)
            {
                var traceDetails = req.details.Where(t => t.index == index).OrderBy(t => t.index).ToList();
                foreach (var detail in traceDetails)
                {
                    var item = items.FirstOrDefault(t => t.id == detail.itemid);
                    if (item == null)
                    {
                        continue;
                    }
                    if (item.value_type == (int)ValueTypeStatus.O)
                    {
                        if (string.IsNullOrWhiteSpace(detail.result))
                        {
                            continue;
                        }
                        insertDetailList.Add(new SnTraceDetailList
                        {
                            TraceID = "",
                            ItemID = detail.itemid,
                            Result = detail.result,
                            Value = detail.value,
                            ItemName = item.item_en,
                            SN = req.sn ?? "",
                            NumberIndex = detail.index,
                            LowerLimit = detail.lowerlimit,
                            UpperLimit = detail.upperlimit,
                        });
                    }
                    else if (item.value_type == (int)ValueTypeStatus.V)
                    {
                        if (detail.value == null && item.value_category != (int)ValueCategory.Maxmin)
                        {
                            continue;
                        }
                        var detailResult = "";
                        if (item.value_category == (int)ValueCategory.Maxmin && !detail.upperlimit.HasValue && !detail.lowerlimit.HasValue)
                        {
                            continue;
                        }
                        if (item.value_category == (int)ValueCategory.Maxmin)
                        {
                            var range = detail.upperlimit.Value - detail.lowerlimit.Value;
                            detail.value = (detail.upperlimit.Value + detail.lowerlimit.Value) / 2;
                            detailResult = "OK";
                            if (detail.upperlimit.Value > item.max_value || detail.lowerlimit.Value < item.min_value ||
                                range > item.range || detail.value.Value > item.max_value || detail.value.Value < item.min_value ||
                                detail.upperlimit.Value < item.min_value || detail.lowerlimit.Value > item.max_value)
                            {
                                detailResult = "NG";
                            }
                        }
                        else
                        {
                            detailResult = (detail.value.Value <= item.max_value && detail.value.Value >= item.min_value) ? "OK" : "NG";
                        }
                        insertDetailList.Add(new SnTraceDetailList
                        {
                            TraceID = "",
                            ItemID = detail.itemid,
                            Result = detailResult,
                            Value = detail.value,
                            ItemName = item.item_en,
                            SN = req.sn ?? "",
                            NumberIndex = detail.index,
                            LowerLimit = detail.lowerlimit,
                            UpperLimit = detail.upperlimit
                        });
                    }
                }
            }

            var trace_id = Guid.NewGuid().ToString();

            #region 插入检验扩展表

            if (req.result.ToUpper() == "OK")
            {
                req.result = ((int)SendTestType.Qalified).ToString();
            }
            else if (req.result.ToUpper() == "NG")
            {
                req.result = ((int)SendTestType.Unqualified).ToString();
            }
            var nowTime = DateTime.Now;
            //插入中间层库的trace表
            var inspection = new siger_check_sn_trace_inspection
            {
                trace_id = trace_id,
                testroom = "",
                productid = req.productid,
                materialid = req.materialid.ToInt(),
                sectionid = req.sectionid,
                sn = req.sn ?? "",
                routeid = req.routeid.ToInt(),
                check_type = req.checktype,
                check_status = (int)SendCheckStatus.Completed,
                result = req.result,
                send_mid = UserId,
                send_time = nowTime,
                check_mid = UserId,
                check_time = nowTime,
                inspection_type = (int)InspectionType.ManualCollection,
                projectId = ProjectId,
                reason = req.reason ?? "",
                workorder = "",
                number = req.number.ToInt(),
                quantity = req.quantity.ToInt()
            };
            _traceInspectionRepository.Insert(inspection);
            //插入中间层库的 检验详情表
            foreach (var detail in insertDetailList)
            {
                var model = new siger_check_sn_trace_detail
                {
                    TraceID = inspection.trace_id,
                    ItemID = detail.ItemID,
                    Result = detail.Result,
                    Value = detail.Value,
                    ItemName = detail.ItemName,
                    SN = req.sn ?? "",
                    NumberIndex = detail.NumberIndex,
                    LowerLimit = detail.LowerLimit,
                    UpperLimit = detail.UpperLimit,
                    projectId = ProjectId,
                    CreateTime = nowTime
                };
                _traceDetailRepository.Insert(model);
            }

            if (_unitOfWork.Commit() > 0)
            {
                try
                {
                    CreateTaskList(req.sectionid, req.productid, product.code, req.sn, req.routeid.ToInt());
                    AddSnList(req.materialid.ToInt(), inspection, product.code, section.parentid);//把二维码插入到 sn_list表
                }
                catch(Exception ex)
                {
                    Logger.WriteLineError(ex.ToString());
                }

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

            #endregion
        }

        private void AddSnList(int materialid, siger_check_sn_trace_inspection trace, string code, int lineId)
        {
            var snEntity = _snListRepository.Get(t => t.projectId == ProjectId && t.status == (int)RowState.Valid &&
                    t.SN == trace.sn && !string.IsNullOrWhiteSpace(trace.sn));
            if (snEntity == null)
            {
                var stateCode = "000";
                var eventNoObj = _snListRepository.GetEventNoByResult(trace.sn, ProjectId);
                if (eventNoObj != null)
                {
                    //出站信息获取
                    var outObj = _snListRepository.GetOutStationByEventNo(eventNoObj.EventNo, trace.sectionid, ProjectId);
                    if (outObj != null)
                    {
                        stateCode = outObj.ResultStatus;
                    }
                }
                var material = _materialsRepository.Get(t => t.projectId == ProjectId && t.status == (int)RowState.Valid &&
                    t.id == materialid);
                var snListObj = new siger_check_sn_list
                {
                    SN = trace.sn,
                    BatchNumber = "",
                    ProductID = trace.productid,
                    ProductCode = code,
                    LineID = lineId,
                    WorkOrder = trace.workorder,
                    MaterialID = material?.id ?? 0,
                    PartNumber = material?.pn ?? "",
                    StateCode = stateCode,
                    CreateTime = DateTime.Now,
                    projectId = ProjectId
                };
                _snListRepository.Insert(snListObj);
                _unitOfWork.Commit();
            }
        }

        private void CreateTaskList(int section, int productid, string productcode, string sn, int routeid)
        {
            if (section <= 0 || string.IsNullOrEmpty(sn) || string.IsNullOrEmpty(productcode) || productid <= 0)
            {
                return;
            }
            var monitor =  _fixtureMonitor.GetList(q => q.section == section && q.sn == sn).OrderByDescending(q => q.updatetime).FirstOrDefault();
            if (monitor == null)
            {
                return;
            }

            var taskNo = _automationTaskList.CrateTaskNumber(Automation.TaskTrigerType.Manual);            

            _automationTaskList.Insert(new siger_automation_task_list
            {
                no = taskNo,
                action = Automation.TaskAction.Step_CJT_SXLW,
                actiontype = Automation.ExcueType.None,
                triggertime = DateTime.MinValue,
                tasktype = Automation.TaskActionType.Unload,
                operater = UserId,
                operatetime = DateTime.Now,
                sectionid = section,
                send = 0,
                status = 1,
                completetime = DateTime.MinValue,
                trigger = Automation.TaskTrigerType.Manual,
                projectId = ProjectId,
                productid = productid,
                sn = sn,
                ordercode = "",
                fixtureguid = monitor.fixtureguid,
                locationid = monitor.locationId,
                productcode = productcode,
                processid = routeid,
                programnumber = "",
                remark = "质量检验",
            });

            _unitOfWork.Commit();
        }
    }
}
