using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Siger.ApiCommon.Result;
using Siger.Middlelayer.QmsRepository.Entities;
using Siger.Middlelayer.QmsRepository.Repositories.Interface;
using Siger.Middlelayer.QmsRepository.Request;
using Siger.Middlelayer.QmsRepository.Response;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Response;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;
using Siger.ApiQMS.Utility;
using Siger.Middlelayer.Common.Helpers;

namespace Siger.ApiQMS.Controllers
{
    public class ManualCollectionController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IInspectStandardRepository _inspectStandard;
        private readonly IProductRouteRepository _productRouteRepository;
        private readonly ISigerProjectProductRepository _productRepository;
        private readonly ISigerProjectLevelSectionRepository _levelSectionRepository;
        private readonly ISigerProjectUserRepository _projectUserRepository;
        private readonly ICheckSnListRepository _snListRepository;
        private readonly ISigerTrMaterialsRepository _materialsRepository;
        private readonly ISigerProjectLevelRepository _levelRepository;
        private readonly ICheckSnTraceInspectionRepository _traceInspectionRepository;
        private readonly IDefaultInfoConfigRepository _defaultInfoConfigRepository;
        private readonly ICheckSnTraceDetailRepository _traceDetailRepository;
        private readonly IQmsTypeCountSettingRepository _typeCountRepository;
        private readonly IAbnormalRuleRepository _abnormalRuleRepository;
        private readonly ISigerDict _sigerDict;
        public ManualCollectionController(IUnitOfWork unitOfWork, IInspectStandardRepository inspectStandard,
            IProductRouteRepository productRouteRepository, ISigerProjectProductRepository productRepository,
            ISigerProjectLevelSectionRepository levelSectionRepository, ISigerProjectUserRepository projectUserRepository,
            ICheckSnListRepository snListRepository, ISigerTrMaterialsRepository materialsRepository,
            ISigerProjectLevelRepository levelRepository, ICheckSnTraceInspectionRepository traceInspectionRepository,
            IDefaultInfoConfigRepository defaultInfoConfigRepository, ICheckSnTraceDetailRepository traceDetailRepository,
            IQmsTypeCountSettingRepository typeCountRepository, IAbnormalRuleRepository abnormalRuleRepository,
            ISigerDict sigerDict)
        {
            _unitOfWork = unitOfWork;
            _inspectStandard = inspectStandard;
            _productRouteRepository = productRouteRepository;
            _productRepository = productRepository;
            _levelSectionRepository = levelSectionRepository;
            _projectUserRepository = projectUserRepository;
            _snListRepository = snListRepository;
            _materialsRepository = materialsRepository;
            _levelRepository = levelRepository;
            _traceInspectionRepository = traceInspectionRepository;
            _defaultInfoConfigRepository = defaultInfoConfigRepository;
            _traceDetailRepository = traceDetailRepository;
            _typeCountRepository = typeCountRepository;
            _abnormalRuleRepository = abnormalRuleRepository;
            _sigerDict = sigerDict;
        }

        /// <summary>
        /// 人工检验数据查询
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetManualPageList(int sectionid, int productid, int materialid, int route, int checktype, string sn, string result, int itemid,
            string starttime, string endtime, string userid, int page, int pagesize, string toexcel)
        {
            var sectionIds = new List<int>();
            if (sectionid > 0)
            {
                sectionIds = _levelSectionRepository.GetLevelSectionIds(sectionid, ProjectId).ToList();
            }
            var dataList = new List<ResponseDataCollection>();
            var res = _traceDetailRepository.GetPagedList(sectionIds, productid, materialid, route, checktype, sn, result, new List<string>(),
                starttime, endtime, userid.ToInt(), itemid, ProjectId, page, pagesize, toexcel);
            var sections = _levelSectionRepository.GetList(t => t.projectid == ProjectId && 
                t.status == (int)RowState.Valid).ToList();            
            foreach (var data in res.Data)
            {
                var model = Mapper<ResponseDataCollection, ResponseDataCollection>.Map(data);
                model.sectionname = ChannelSectionHelper.GetChannelSection(data.sectionid, sections);
                dataList.Add(model);
            }
            if(toexcel.ToInt() > 0)
            {
                return ExportExcel(dataList);
            }
            return new PagedLongTotalObjectResult(dataList, res.Total, page, pagesize);
        }

        [HttpPost]
        public IActionResult Add([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
                {
                    AddSnList(req.materialid.ToInt(), inspection, product.code, section.parentid);//把二维码插入到 sn_list表

                    var abnormalCheckHelper = new AbnormalCheckHelper(_unitOfWork, _abnormalRuleRepository, _projectUserRepository,
                            _traceDetailRepository, _inspectStandard, _traceInspectionRepository, _sigerDict, CompanyId, ProjectId, UserId);
                    abnormalCheckHelper.AbnomalRuleCheck(inspection.number, inspection.trace_id, inspection.sectionid, machine?.id ?? 0, true, req.checktype);
                }
                catch(Exception ex)
                {
                    Logger.WriteLineError(ex.ToString());
                }

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

            #endregion
        }

        [HttpGet]
        public IActionResult ExportExcel(List<ResponseDataCollection> data)
        {
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);

            if (!data.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var dataList = new List<ManualCollectionList>();
            var dataDetailList = new List<ManualCollectionDetailList>();
            int index = 1;
            var levelSections = _levelSectionRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid).ToList();

            var ids = data.Select(q => q.id).Distinct().ToList();
            var details = _traceDetailRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                    ids.Contains(t.TraceID)).ToList();

            var items = _inspectStandard.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid).ToList();
            var configs = _defaultInfoConfigRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid).ToList();
            foreach (var item in data)
            {
                dataList.Add(new ManualCollectionList
                {
                    No = index,
                    ProductCode = item.productcode,
                    ProductName = item.productname,
                    RouteName = item.routename,
                    Section = ChannelSectionHelper.GetChannelSection(item.sectionid, levelSections),
                    WorkOrder = item.workorder,
                    SN = item.sn,
                    Result = item.result,
                    CheckUser = item.check_user,
                    CheckTime = item.check_time,
                    Quantity = item.result == ((int)SendTestType.DeviationRelease).ToString() ? item.quantity.ToString() : "",
                    Reason = item.reason ?? ""
                });
                var dataDetails = details.Where(q => q.TraceID == item.id).ToList();
                var detailIndex = 1;
                foreach (var detail in dataDetails)
                {
                    var config = configs.FirstOrDefault(t => t.key == detail.ItemName);
                    var standardItem = items.FirstOrDefault(t => t.id == detail.ItemID);
                    var minValue = standardItem != null ? (standardItem.value_type == (int)ValueTypeStatus.V ? standardItem.min_value.ToString() ?? "" : "") : "";
                    var maxValue = standardItem != null ? (standardItem.value_type == (int)ValueTypeStatus.V ? standardItem.max_value.ToString() ?? "" : "") : "";
                    if (minValue == QmsLimitValue.MinValue)
                    {
                        minValue = "";
                    }
                    if (maxValue == QmsLimitValue.MaxValue)
                    {
                        maxValue = "";
                    }
                    dataDetailList.Add(new ManualCollectionDetailList
                    {
                        No = detailIndex,
                        Item = standardItem?.item ?? detail.ItemName,
                        Standard = standardItem?.standard ?? "",
                        MinValue = minValue,
                        MaxValue = maxValue,
                        DetailResult = detail.Result,
                        Value = detail.Value.HasValue ? detail.Value.ToString() : "",
                        Description = config?.description ?? "",
                        Range = standardItem == null ? "" : standardItem.range.ToString(),
                        LowerLimit = detail.LowerLimit.HasValue ? detail.LowerLimit.Value.ToString() : "",
                        UpperLimit = detail.UpperLimit.HasValue ? detail.UpperLimit.Value.ToString() : "",
                        ActualRange = detail.LowerLimit.HasValue && detail.UpperLimit.HasValue ?
                            Math.Round(detail.UpperLimit.Value - detail.LowerLimit.Value, 4).ToString() : ""
                    });
                    detailIndex++;
                }
                index++;
            }
            if (dataList.Any())
            {
                EpPlusExcelHelper<ManualCollectionList> helper = null;
                try
                {
                    helper = new EpPlusExcelHelper<ManualCollectionList>();
                    var temporaryFileName = $"人工检验数据_ManualInspectionData_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
                    helper.GenerateExcel(dataList, dataDetailList, Path.Combine(rootDir, temporaryFileName));
                    return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
                }
                catch (Exception e)
                {
                    Logger.WriteLineError("Export Manual Inspection Data failed, error:" + e);
                    throw new BadRequestException(RequestEnum.ExportFailed);
                }
                finally
                {
                    helper?.Dispose();
                }
            }

            throw new BadRequestException(CommonEnum.Fail);
        }

        /// <summary>
        /// 编辑页面获取详情
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetDetails(int productid, int sectionid, string id)
        {
            var res = new List<ResponseDataCollectionDetail>();
            if (!string.IsNullOrEmpty(id))
            {
                var dataDetails = _traceDetailRepository.GetList(q => q.TraceID == id && q.projectid == ProjectId && q.status == (int)RowState.Valid).ToList();
                var standards = _inspectStandard.GetList(t => t.productid == productid &&
                    t.sectionid == sectionid && t.projectid == ProjectId &&
                    t.status == (int)RowState.Valid).ToList();

                foreach (var standard in standards)
                {
                    if (dataDetails.Any())
                    {
                        var details = dataDetails.Where(t => t.ItemID == standard.id).ToList();
                        foreach (var detail in details)
                        {
                            var model = new ResponseDataCollectionDetail
                            {
                                id = detail.ID,
                                itemid = detail.ItemID,
                                max_value = standard.max_value,
                                min_value = standard.min_value,
                                result = detail.Result,
                                value = detail.Value,
                                item = standard.item,
                                standard = standard.standard,
                                checktype = standard.value_type
                            };
                            res.Add(model);
                        }
                    }
                }
            }
            else
            {
                var standards = _inspectStandard.GetList(t =>
                    t.productid == productid && t.sectionid == sectionid && t.projectid == ProjectId
                    && t.status == (int)RowState.Valid).ToList();
                foreach (var standard in standards)
                {
                    var model = new ResponseDataCollectionDetail
                    {
                        id = 0,
                        itemid = standard.id,
                        max_value = standard.max_value,
                        min_value = standard.min_value,
                        result = "",
                        value = null,
                        item = standard.item,
                        standard = standard.standard,
                        checktype = standard.value_type
                    };
                    res.Add(model);
                }
            }
            return new ObjectResult(res);
        }
        /// <summary>
        /// 获取详情-从siger库
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetDetailList(string id)
        {
            var res = new List<ResponseDataCollectionDetail>();
            var dataDetails = _traceDetailRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                t.TraceID == id).ToList();

            var configKeys = dataDetails.Select(t => t.ItemName).ToList();
            var configs = _defaultInfoConfigRepository.GetList(t => configKeys.Contains(t.key)).ToList();
            foreach (var detail in dataDetails)
            {
                var standard = _inspectStandard.Get(t => t.id == detail.ItemID);
                var config = configs.FirstOrDefault(t => t.key == detail.ItemName);
                var model = new ResponseDataCollectionDetail
                {
                    id = detail.ID,
                    itemid = detail.ItemID,
                    max_value = standard?.max_value ?? 0,
                    min_value = standard?.min_value ?? 0,
                    result = detail.Result,
                    value = detail.Value,
                    item = standard?.item ?? detail.ItemName,
                    standard = standard?.standard ?? "",
                    checktype = standard?.value_type ?? 0,
                    description = config?.description ?? "",
                    valuecategory = standard?.value_category ?? 0,
                    upperlimit = detail.UpperLimit,
                    lowerlimit = detail.LowerLimit,
                    range = (detail.LowerLimit.HasValue && detail.UpperLimit.HasValue) ?
                        Math.Round(detail.UpperLimit.Value - detail.LowerLimit.Value, 4) : 0,
                    item_range = standard?.range ?? 0
                };
                res.Add(model);
            }
            return new ObjectResult(res);
        }
        /// <summary>
        /// 获取详情-从大数据库
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetTraceDetailList(string id)
        {
            var res = new List<ResponseDataCollectionDetail>();
            var dataDetails = _traceDetailRepository.GetList(q => q.projectid == ProjectId && q.status == (int)RowState.Valid && q.TraceID == id).ToList();

            var configKeys = dataDetails.Select(t => t.ItemName).ToList();
            var configs = _defaultInfoConfigRepository.GetList(t => configKeys.Contains(t.key)).ToList();
            foreach (var detail in dataDetails)
            {
                var standard = _inspectStandard.Get(t => t.id == detail.ItemID);
                var config = configs.FirstOrDefault(t => t.key == detail.ItemName);
                var model = new ResponseDataCollectionDetail
                {
                    id = detail.ID,
                    itemid = detail.ItemID,
                    max_value = standard?.max_value ?? 0,
                    min_value = standard?.min_value ?? 0,
                    result = detail.Result,
                    value = detail.Value,
                    item = standard?.item ?? detail.ItemName,
                    standard = standard?.standard ?? "",
                    checktype = standard?.value_type ?? 0,
                    description = config?.description ?? "",
                    valuecategory = standard?.value_category ?? 0,
                    item_range = standard?.range ?? 0
                };
                res.Add(model);
            }
            return new ObjectResult(res);
        }

        /// <summary>
        /// 通过工位和产品从工艺路由取到工序
        /// </summary>
        /// <param name="productid"></param>
        /// <param name="sectionid"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetSectionRoutes(int productid, int sectionid)
        {
            var res = new List<ResponseIdName>();
            var product = _productRepository.Get(t => t.id == productid && t.status == (int)RowState.Valid);
            if (product != null)
            {
                res = _inspectStandard.GetSectionRouteList(product.code, sectionid, ProjectId).ToList();
            }

            return new ObjectResult(res);
        }

        [HttpGet]
        public IActionResult Delete(string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var inspections = _traceInspectionRepository.GetList(t =>
                t.trace_id == id && t.projectid == ProjectId && t.status == (int)RowState.Valid).ToList();
            var details = _traceDetailRepository.GetList(t =>
                t.TraceID == id && t.projectid == ProjectId && t.status == (int)RowState.Valid).ToList();
            foreach (var inspection in inspections)
            {
                inspection.status = (int)RowState.Invalid;
                _traceInspectionRepository.Update(inspection);
            }
            foreach (var detail in details)
            {
                detail.status = (int)RowState.Invalid;
                _traceDetailRepository.Update(detail);
            }
            if(_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            else
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }

        [HttpPost]
        public IActionResult Update([FromBody]RequestUpdateDataCollection req)
        {
            var inspection = _traceInspectionRepository.Get(t => t.status == (int)RowState.Valid && t.projectid == ProjectId &&
                t.trace_id == req.id);
            if (inspection == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

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

            var delTraceDetails = _traceDetailRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                t.TraceID == req.id).ToList();

            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 = "";
            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
                        });
                    }
                }
            }
            #region 插入检验扩展表

            if (req.result.ToUpper() == "OK")
            {
                req.result = ((int)SendTestType.Qalified).ToString();
            }
            else if (req.result.ToUpper() == "NG")
            {
                req.result = ((int)SendTestType.Unqualified).ToString();
            }

            inspection.result = req.result;
            inspection.quantity = req.quantity.ToInt();
            _traceInspectionRepository.Update(inspection);

            foreach (var delDetail in delTraceDetails)
            {
                delDetail.status = (int)RowState.Invalid;
                _traceDetailRepository.Update(delDetail);
            }

            foreach (var detail in insertDetailList)
            {
                var model = new siger_check_sn_trace_detail
                {
                    TraceID = req.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 = inspection.checking_time.HasValue ? inspection.checking_time.Value : DateTime.Now,
                };
                _traceDetailRepository.Insert(model);
            }

            if (_unitOfWork.Commit() > 0)
            {
                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();
            }
        }

        [HttpGet]
        public IActionResult GetUpdateDetails(string id)
        {
            var res = new ResponseDataCollectionDetailList();
            var trace = _traceInspectionRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid && t.trace_id == id
                && t.inspection_type == (int)InspectionType.ManualCollection);
            if(trace == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var typeOne = trace.check_type.ToString(); var typeEnd = $",{typeOne}"; var typeStart = $"{typeOne},"; var typeTwo = $",{typeOne},";//精确匹配，避免类似12匹配到1的情况
            var items = _inspectStandard.GetList(t => t.status == (int)RowState.Valid && t.projectid == ProjectId &&
                t.productid == trace.productid && t.sectionid == trace.sectionid && t.standard_type == (int)StandardType.ManualCollection &&
                (t.checktype.Contains(",") ? (t.checktype.Contains(typeTwo) || t.checktype.StartsWith(typeStart) || t.checktype.EndsWith(typeEnd)) : (t.checktype == typeOne))).ToList();
            var dataDetails = _traceDetailRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                 t.TraceID == id).ToList();
            foreach (var detail in dataDetails)
            {
                var standard = items.FirstOrDefault(t => t.id == detail.ItemID);
                if(standard == null)
                {
                    continue;
                }
                var model = new ResponseDataCollectionDetails
                {
                    id = detail.ID,
                    itemid = standard.id,
                    max_value = standard.max_value,
                    min_value = standard.min_value,
                    result = detail.Result,
                    value = detail.Value,
                    item = standard.item,
                    standard = standard.standard,
                    checktype = standard.value_type,
                    range = detail.LowerLimit.HasValue && detail.UpperLimit.HasValue ?
                            Math.Round(detail.UpperLimit.Value - detail.LowerLimit.Value, 4) : 0,
                    valuecategory = standard.value_category,
                    lowerlimit = detail.LowerLimit,
                    upperlimit = detail.UpperLimit,
                    index = detail.NumberIndex
                };
                res.details.Add(model);
            }
            foreach (var standard in items)
            {
                var model = new ResponseDataCollectionDetails
                {
                    id = 0,
                    itemid = standard.id,
                    max_value = standard.max_value,
                    min_value = standard.min_value,
                    result = "",
                    value = null,
                    item = standard.item,
                    standard = standard.standard,
                    checktype = standard.value_type,
                    valuecategory = standard.value_category,
                    range = standard.range,
                };
                res.itemdetails.Add(model);
            }
            var tyepCount = _typeCountRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                t.type_code == trace.check_type);
            res.number = tyepCount?.check_count ?? 0;
            return new ObjectResult(res);
        }
    }
}