using Microsoft.AspNetCore.Mvc;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository;
using System;
using System.Collections.Generic;
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.Common.Helpers;
using UploadFileModel = Siger.Middlelayer.QmsRepository.Response.UploadFileModel;
using Siger.Middlelayer.Log;
using System.IO;
using Siger.Middlelayer.Common.AppSettings;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.Utility.ImportEntities;
using Siger.Middlelayer.Utility.Helpers;
using System.Linq.Expressions;
using Siger.Middlelayer.Repository.Extensions;
using Siger.ApiQMS.Utility;
using Siger.Middlelayer.Share.ModuleEnum;

namespace Siger.ApiQMS.Controllers
{
    public class IncomingMaterialController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IInspectStandardMaterialRepository _inspectStandard;
        private readonly ISigerProjectLevelSectionRepository _levelSectionRepository;
        private readonly ICheckSnTraceMaterialRepository _traceMaterialRepository;
        private readonly ICheckSnTraceMaterialDetailRepository _traceMaterialdetailRepository;
        private readonly ICheckSnTraceFileRepository _traceFileRepository;
        private readonly ICheckSnListRepository _snListRepository;
        private readonly ISigerTrMaterialsRepository _materialsRepository;
        private readonly ISigerProjectLevelRepository _levelRepository;
        private readonly ISigerProjectMachineAttributionRepository _machineAttributionRepository;
        private readonly Isiger_wms_bussinese_contactsRepository _contactsRepository;
        private readonly ISigerDict _sigerDict;
        private readonly ISigerProjectSectionRepository _projectSectionRepository;

        public IncomingMaterialController(IUnitOfWork unitOfWork, IInspectStandardMaterialRepository inspectStandard,
            ISigerProjectLevelSectionRepository levelSectionRepository, ICheckSnTraceMaterialRepository traceMaterialRepository,
            ICheckSnTraceMaterialDetailRepository traceMaterialDetailRepository, ICheckSnTraceFileRepository traceFileRepository,
            ICheckSnListRepository snListRepository, ISigerTrMaterialsRepository materialsRepository,
            ISigerProjectLevelRepository levelRepository, ISigerProjectMachineAttributionRepository machineAttributionRepository
            , Isiger_wms_bussinese_contactsRepository contactsRepository, ISigerDict sigerDict,
            ISigerProjectSectionRepository sigerProjectSectionRepository)
        {
            _unitOfWork = unitOfWork;
            _inspectStandard = inspectStandard;
            _levelSectionRepository = levelSectionRepository;
            _traceMaterialRepository = traceMaterialRepository;
            _traceMaterialdetailRepository = traceMaterialDetailRepository;
            _traceFileRepository = traceFileRepository;
            _snListRepository = snListRepository;
            _materialsRepository = materialsRepository;
            _levelRepository = levelRepository;
            _machineAttributionRepository = machineAttributionRepository;
            _contactsRepository = contactsRepository;
            _sigerDict = sigerDict;
            _projectSectionRepository = sigerProjectSectionRepository;
        }

        [HttpGet]
        [ProducesDefaultResponseType(typeof(ResponseIncomingMaterial))]
        public IActionResult GetPageList(int sectionid, int supplierid, int materialid, string result,
                string batchnumber, string starttime, string endtime, int page, int pagesize, string toexcel)
        {
            var sectionIds = new List<int>();
            if (sectionid > 0)
            {
                sectionIds = _levelSectionRepository.GetLevelSectionIds(sectionid, ProjectId).ToList();
            }
            var list = new List<ResponseIncomingMaterial>();
            var datas = _traceMaterialRepository.GetPagedList(sectionIds, materialid, supplierid,
                result, batchnumber, starttime, endtime, page, pagesize, ProjectId, toexcel);
            if (datas.Data.Any())
            {
                var levelSections = _levelSectionRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid).ToList();
                var traceIds = datas.Data.Select(t => t.id).ToList();
                var fileList = _traceFileRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                    traceIds.Contains(t.trace_id) && t.trace_type == (int)FileTraceType.InComingMaterial).ToList();
                foreach (var item in datas.Data)
                {
                    var model = Mapper<ResponseIncomingMaterial, ResponseIncomingMaterial>.Map(item);
                    var images = fileList.Where(t => t.file_type == (int)TraceFileType.Image && t.trace_id == item.id).ToList();
                    var files = fileList.Where(t => t.file_type == (int)TraceFileType.File && t.trace_id == item.id).ToList();
                    foreach (var image in images)
                    {
                        model.images.Add(new UploadFileModel
                        {
                            url = image.url,
                            name = image.name,
                            size = image.size
                        });
                    }
                    foreach (var file in files)
                    {
                        model.files.Add(new UploadFileModel
                        {
                            url = file.url,
                            name = file.name,
                            size = file.size
                        });
                    }
                    model.sectionname = ChannelSectionHelper.GetChannelSection(item.sectionid, levelSections);
                    list.Add(model);
                }
            }


            if (toexcel.ToInt() == 1)
            {
                return ExportExcel(list);
            }
            return new PagedObjectResult(list, datas.Total, page, pagesize);
        }

        [HttpPost]
        public IActionResult Add([FromBody]RequestIncomingMaterial req)
        {
            var material = _materialsRepository.Get(t => t.projectId == ProjectId && t.status == (int)RowState.Valid &&
                t.id == req.materialid);
            if (material == null)
            {
                throw new BadRequestException(RequestEnum.MaterialNotExist);
            }
            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 result = req.result.ToInt();
            if (result <= 0)
            {
                throw new BadRequestException(RequestEnum.SelectCheckResult);
            }

            if (req.details == null || !req.details.Any())
            {
                throw new BadRequestException(RequestEnum.ParameterMiss);
            }
            if (req.details.Count == req.details.Max(t => t.index))
            {
                req.details = req.details.Where(t => !string.IsNullOrEmpty(t.sn)).ToList();
                if (!req.details.Any())
                {
                    throw new BadRequestException(RequestEnum.ParameterMiss);
                }
                var Sns = req.details.Where(t => !string.IsNullOrEmpty(t.sn)).ToList();
                foreach (var sn in Sns)
                {
                    if (Sns.Count(t => t == sn) > 1)
                    {
                        throw new BadRequestException(RequestEnum.SnDontRepeat);
                    }
                }
                var trace = new siger_check_sn_trace_material
                {
                    MaterialID = req.materialid,
                    PartNumber = material.pn,
                    ProductID = 0,
                    SectionID = req.sectionid,
                    SupplierID = req.supplierid.ToInt(),
                    TotalQuantity = req.totalquantity,
                    RandomCheckNumber = req.randomchecknumber,
                    Result = req.result ?? "",
                    BatchNumber = req.batchnumber ?? "",
                    UserID = UserId,
                    projectid = ProjectId,
                    CreateTime = DateTime.Now,
                    SN = req.incomingsn ?? "",
                    PO = req.PO ?? "",
                    ArrivalDate = req.date.ToDateTime(),
                    Remark = req.remark ?? ""
                };
                _traceMaterialRepository.Insert(trace);
                if (_unitOfWork.Commit() > 0)
                {
                    var insertDetailList = new List<siger_check_sn_trace_material_detail>();
                    foreach (var detail in req.details)
                    {
                        insertDetailList.Add(new siger_check_sn_trace_material_detail
                        {
                            TraceID = trace.id,
                            ItemID = 0,
                            ItemName = "",
                            Result = "",
                            Value = null,
                            UserID = UserId,
                            CreateTime = DateTime.Now,
                            projectid = ProjectId,
                            SN = detail.sn ?? "",
                            NumberIndex = detail.index,

                        });
                    }
                    _traceMaterialdetailRepository.Insert(insertDetailList);
                    SaveFiles(req.files, req.images, trace.id);
                    if (_unitOfWork.Commit() > 0)
                    {
                        var snList = req.details.Where(t => !string.IsNullOrEmpty(t.sn)).Select(t => t.sn).Distinct().ToList();
                        AddSNList(snList, req.materialid, material.pn, req.batchnumber, 0, "", section.parentid, section.id);
                        return new ObjectResult(CommonEnum.Succefull);
                    }
                    else
                    {
                        throw new BadRequestException(CommonEnum.Fail);
                    }
                }
                else
                {
                    throw new BadRequestException(CommonEnum.Fail);
                }
            }
            else
            {
                var indexs = req.details.Select(t => t.index).Distinct().ToList();
                var items = _inspectStandard.GetList(t => req.details.Select(q => q.itemid).Contains(t.id)).ToList();
                foreach (var index in indexs)
                {
                    var Sns = new List<string>();
                    var traceDetails = req.details.Where(t => t.index == index).OrderBy(t => t.index).ToList();
                    if (traceDetails.Any())
                    {
                        traceDetails.RemoveAt(0);
                        if (!string.IsNullOrEmpty(traceDetails.FirstOrDefault().sn))
                        {
                            Sns.Add(traceDetails.FirstOrDefault().sn);
                        }
                        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);
                            }
                        }
                    }
                    foreach (var sn in Sns)
                    {
                        if (Sns.Count(t => t == sn) > 1)
                        {
                            throw new BadRequestException(RequestEnum.SnDontRepeat);
                        }
                    }
                }
                var trace = new siger_check_sn_trace_material
                {
                    MaterialID = req.materialid,
                    PartNumber = material.pn,
                    ProductID = 0,
                    SectionID = req.sectionid,
                    SupplierID = req.supplierid.ToInt(),
                    TotalQuantity = req.totalquantity,
                    RandomCheckNumber = req.randomchecknumber,
                    Result = req.result ?? "",
                    BatchNumber = req.batchnumber ?? "",
                    UserID = UserId,
                    projectid = ProjectId,
                    CreateTime = DateTime.Now,
                    SN = req.incomingsn ?? "",
                    PO = req.PO ?? "",
                    ArrivalDate = req.date.ToDateTime(),
                    Remark = req.remark ?? ""
                };
                _traceMaterialRepository.Insert(trace);
                if (_unitOfWork.Commit() > 0)
                {
                    SaveFiles(req.files, req.images, trace.id);
                    var insertDetailList = new List<siger_check_sn_trace_material_detail>();
                    foreach (var index in indexs)
                    {
                        var traceDetails = req.details.Where(t => t.index == index).OrderBy(t => t.index).ToList();
                        if (traceDetails.Any())
                        {
                            traceDetails.RemoveAt(0);
                        }                        
                        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 siger_check_sn_trace_material_detail
                                {
                                    TraceID = trace.id,
                                    ItemID = item.id,
                                    ItemName = item.item,
                                    Result = detail.result,
                                    Value = null,
                                    UserID = UserId,
                                    CreateTime = DateTime.Now,
                                    projectid = ProjectId,
                                    SN = detail.sn ?? "",
                                    NumberIndex = detail.index,
                                });
                            }
                            else if (item.value_type == (int)ValueTypeStatus.V)
                            {
                                if (detail.value == null && item.value_category != (int)ValueCategory.Maxmin)
                                {
                                    continue;
                                }
                                if (item.value_category == (int)ValueCategory.Maxmin && !detail.upperlimit.HasValue && !detail.lowerlimit.HasValue)
                                {
                                    continue;
                                }
                                var detailResult = "";
                                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 siger_check_sn_trace_material_detail
                                {
                                    TraceID = trace.id,
                                    ItemID = item.id,
                                    ItemName = item.item,
                                    Result = detailResult,
                                    Value = detail.value,
                                    UserID = UserId,
                                    CreateTime = DateTime.Now,
                                    projectid = ProjectId,
                                    SN = detail.sn ?? "",
                                    NumberIndex = detail.index,
                                    UpperLimit = detail.upperlimit,
                                    LowerLimit = detail.lowerlimit,
                                });
                            }                            
                        }
                    }
                    _traceMaterialdetailRepository.Insert(insertDetailList);
                    if (_unitOfWork.Commit() > 0)
                    {
                        var snList = req.details.Where(t => !string.IsNullOrEmpty(t.sn)).Select(t => t.sn).Distinct().ToList();
                        AddSNList(snList, req.materialid, material.pn, req.batchnumber, 0, "", section.parentid, section.id);

                        if(req.result.ToInt() == (int)IncomingMaterialType.Rejection)
                        {
                            InsertKpiTaskList();
                        }                        
                        return new ObjectResult(CommonEnum.Succefull);
                    }
                    else
                    {
                        throw new BadRequestException(CommonEnum.Fail);
                    }
                }
                else
                {
                    throw new BadRequestException(CommonEnum.Fail);
                }
            }
        }

        private void InsertKpiTaskList()
        {
            var dict = _sigerDict.Get(t => t.projectId == ProjectId && t.status == (int)RowState.Valid && t.cat == AccDictCost.QmsCheckNgKpi);
            if(string.IsNullOrEmpty(dict?.dval))
            {
                return;
            }
            var dictValues = dict.dval.Split(';').ToList();
            if(dictValues.Count != 3)
            {
                return;
            }
            //入厂检年度供应商不合格数据自动关联图表：通过KPI维护，按月及累积值维护；
            //SKF内部确认是否添加表格-- - 方案：当进料检验结果为拒收时，
            //自动塞一笔数据到KPI日常数据中（批次数），实际值当天 + 1，
            //累计值按照月进行累计，塞到哪个部门的哪个指标下通过字典进行维护，
            //Value是部门名称 +“;”指标名称 +“;”+周期

            var department = _projectSectionRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                t.title == dictValues[0]);
            var item = _inspectStandard.GetKpiItem(dictValues[1], ProjectId);
            if(item == null || department == null)
            {
                return;
            }
            var now = DateTime.Now;
            var today = DateTime.Today;
            var dayCount = 0;
            var mouthCount = 0;
            var cycle = string.Empty;
            switch (dictValues[2])
            {
                case "日":
                case "day":
                    {
                        cycle = now.ToString(ParameterConstant.DateFormat);
                        dayCount = _inspectStandard.GetKpiTaskCount(department.id, item.id, cycle, today,
                                today.AddDays(1).AddSeconds(-1), ProjectId);
                        var stime = today.ToString(ParameterConstant.MouthFirstDay).ToDateTime();
                        var etime = today.AddSeconds(-1);
                        mouthCount = _inspectStandard.GetKpiTaskCount(department.id, item.id, cycle,
                                stime, etime, ProjectId);
                        break;
                    }
                case "周":
                case "week":
                    {
                        cycle = $"{DateTime.Now.Year}{DateTimeHelper.GetTimeStrByType(1, DateTime.Now)}";
                        var thisWeek = DateTimeHelper.GetTimeStartByType(1, today);
                        dayCount = _inspectStandard.GetKpiTaskCount(department.id, item.id, cycle,
                            thisWeek, today.AddDays(1).AddSeconds(-1), ProjectId);
                        if(thisWeek.Month == 1 && thisWeek.Day == 1)
                        {
                            mouthCount = 0;
                        }
                        else
                        {
                            var stime = DateTimeHelper.GetTimeStartByType(1, today.AddDays(-7));
                            var etime = DateTimeHelper.GetTimeEndByType(1, today.AddDays(-7));
                            mouthCount = _inspectStandard.GetKpiTaskCount(department.id, item.id, cycle,
                                    stime, etime, ProjectId);
                        }
                        break;
                    }
                case "月":
                case "mouth":
                    {
                        cycle = now.ToString(ParameterConstant.YearMonthFormat);
                        dayCount = _inspectStandard.GetKpiTaskCount(department.id, item.id, cycle, 
                            DateTimeHelper.GetTimeStartByType(2, today), today.AddDays(1).AddSeconds(-1), ProjectId);
                        if(today.Month == 1)
                        {
                            mouthCount = 0;
                        }
                        else
                        {
                            var stime = DateTimeHelper.GetTimeStartByType(2, today.AddMonths(-1));
                            var etime = DateTimeHelper.GetTimeEndByType(2, today.AddMonths(-1));
                            mouthCount = _inspectStandard.GetKpiTaskCount(department.id, item.id, cycle,
                                    stime, etime, ProjectId);
                        }
                        break;
                    }
                case "季度":
                case "season":
                    {
                        cycle = $"{DateTime.Now.Year}{DateTimeHelper.GetTimeStrByType(5, DateTime.Now)}";
                        dayCount = _inspectStandard.GetKpiTaskCount(department.id, item.id, cycle,
                            DateTimeHelper.GetTimeStartByType(5, today), today.AddDays(1).AddSeconds(-1), ProjectId);
                        if(today.Month <= 3 && today.Month >= 1)
                        {
                            mouthCount = 0;
                        }
                        else
                        {
                            var stime = DateTimeHelper.GetTimeStartByType(5, today.AddMonths(-3));
                            var etime = DateTimeHelper.GetTimeEndByType(5, today.AddMonths(-3));
                            mouthCount = _inspectStandard.GetKpiTaskCount(department.id, item.id, cycle,
                                    stime, etime, ProjectId);
                        }
                        break;
                    }
                case "年":
                case "year":
                    {
                        cycle = $"{DateTime.Now.Year}";
                        dayCount = _inspectStandard.GetKpiTaskCount(department.id, item.id, cycle,
                            DateTimeHelper.GetTimeStartByType(4, today), today.AddDays(1).AddSeconds(-1), ProjectId);
                        var stime = DateTimeHelper.GetTimeStartByType(4, today.AddYears(-1));
                        var etime = DateTimeHelper.GetTimeEndByType(4, today.AddYears(-1));
                        mouthCount = _inspectStandard.GetKpiTaskCount(department.id, item.id, cycle,
                                stime, etime, ProjectId);
                        break;
                    }
                default:
                    return;
            }
            var entity = new SigerProjectKpiTasklist
            {
                Busidate = DateTimeHelper.GetDate(DateTime.Now),
                Section = department.id,
                ItemId = item.id,
                ActVal = dayCount + 1,
                Result = (int)KpiTaskResult.Exception,
                Excption = (int)KpiExecption.Default,
                Type = (int)KpiTaskType.Exception,
                cycle = cycle,
                Remark = "",
                TargetVal = 0,
                AddVal = mouthCount + 1,
                projectid = ProjectId
            };
            if (dayCount == 0)
            {
                _inspectStandard.InsertKpiTaskList(entity);
            }
            else
            {
                _inspectStandard.UpdateKpiTaskList(entity);
            }
        }

        private void SaveFiles(List<InsertFileModel> files, List<InsertFileModel> images, int traceId)
        {
            var fileList = new List<siger_check_sn_trace_file>();
            foreach (var image in images)
            {
                fileList.Add(new siger_check_sn_trace_file
                {
                    trace_id = traceId,
                    url = image.url,
                    name = image.name,
                    size = image.size,
                    projectid = ProjectId,
                    file_type = (int)TraceFileType.Image,
                    trace_type = (int)FileTraceType.InComingMaterial
                });
            }
            foreach (var file in files)
            {
                fileList.Add(new siger_check_sn_trace_file
                {
                    trace_id = traceId,
                    url = file.url,
                    name = file.name,
                    size = file.size,
                    projectid = ProjectId,
                    file_type = (int)TraceFileType.File,
                    trace_type = (int)FileTraceType.InComingMaterial
                });
            }
            _traceFileRepository.Insert(fileList);
        }

        private bool AddSNList(List<string> snList, int materialId, string partNumber, string batchNumber, int productId, string productCode, int lineId, int sectionId)
        {
            foreach (var sn in snList)
            {
                var snEntity = _snListRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                    t.SN == sn && !string.IsNullOrWhiteSpace(sn));
                var stateCode = "000";
                var eventNoObj = _snListRepository.GetEventNoByResult(sn, ProjectId);
                if (eventNoObj != null)
                {
                    //出站信息获取
                    var outObj = _snListRepository.GetOutStationByEventNo(eventNoObj.EventNo, sectionId, ProjectId);
                    if (outObj != null)
                    {
                        stateCode = outObj.ResultStatus;
                    }
                }
                if (snEntity == null)
                {                    
                    var snListObj = new siger_check_sn_list
                    {
                        SN = sn,
                        BatchNumber = batchNumber ?? "",
                        ProductID = productId,
                        ProductCode = productCode,
                        LineID = lineId,
                        WorkOrder = "",
                        MaterialID = materialId,
                        PartNumber = partNumber,
                        StateCode = stateCode,
                        CreateTime = DateTime.Now,
                        projectid = ProjectId
                    };
                    _snListRepository.Insert(snListObj);
                }
                else
                {
                    snEntity.BatchNumber = batchNumber ?? "";
                    snEntity.StateCode = stateCode;
                    _snListRepository.Update(snEntity);
                }
            }
            return _unitOfWork.Commit() > 0;
        }

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

            if (!data.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var dataList = new List<IncomingMaterialList>();
            var dataDetailList = new List<IncomingMaterialDetailList>();
            int index = 1;
            var levelSections = _levelSectionRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid).ToList();
            foreach (var item in data)
            {
                dataList.Add(new IncomingMaterialList
                {
                    No = index,
                    MaterialPn = item.materialpn,
                    MaterialName = item.materialname,
                    MaterialSpec = item.materialspec,
                    Section = ChannelSectionHelper.GetChannelSection(item.sectionid, levelSections),
                    Supplier = item.suppliername,
                    batchNumber = item.batchnumber,
                    TotalQuantity = item.totalquantity,
                    RandomCheckNumber = item.randomchecknumber,
                    Result = item.result,
                    CheckUser = item.check_user,
                    CheckTime = item.check_time,
                    PO = item.po,
                    Remark = item.remark,
                    ArrivalDate = item.date
                });
                var dataDetails = _traceMaterialdetailRepository.GetList(t => t.projectid == ProjectId &&
                    t.status == (int)RowState.Valid && t.TraceID == item.id).ToList();
                var items = _inspectStandard.GetList(t => dataDetails.Select(q => q.ItemID).Contains(t.id)).ToList();
                var detailIndex = 1;
                foreach (var detail in dataDetails)
                {
                    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 IncomingMaterialDetailList
                    {
                        No = detailIndex,
                        SN = detail.SN,
                        Item = standardItem?.item ?? detail.ItemName,
                        Standard = standardItem?.standard ?? "",
                        MinValue = minValue,
                        MaxValue = maxValue,
                        DetailResult = detail.Result,
                        Value = detail.Value.HasValue ? detail.Value.ToString() : "",
                        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<IncomingMaterialList> helper = null;
                try
                {
                    helper = new EpPlusExcelHelper<IncomingMaterialList>();
                    var temporaryFileName = $"进料检验数据_IncomingMaterialInspetionData_{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 Incoming Material Inspetion Data failed, error:" + e);
                    throw new BadRequestException(RequestEnum.ExportFailed);
                }
                finally
                {
                    helper?.Dispose();
                }
            }

            throw new BadRequestException(CommonEnum.Fail);
        }

        [HttpGet]
        public IActionResult GetDetails(int id)
        {
            var data = _traceMaterialRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid && t.id == id);
            if (data == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var res = new List<IncomingMaterialDetails>();
            var details = _traceMaterialdetailRepository.GetList(t => t.projectid == ProjectId &&
                t.status == (int)RowState.Valid && t.TraceID == data.id).ToList();
            var items = _inspectStandard.GetList(t => details.Select(q => q.ItemID).Contains(t.id)).ToList();
            foreach (var detail in details)
            {
                var item = items.FirstOrDefault(t => t.id == detail.ItemID);
                res.Add(new IncomingMaterialDetails
                {
                    id = detail.id,
                    itemid = detail.ItemID,
                    itmename = item?.item ?? detail.ItemName,
                    max_value = item?.max_value ?? 0,
                    min_value = item?.min_value ?? 0,
                    standard = item?.standard ?? "",
                    result = detail.Result,
                    value = detail.Value,
                    sn = detail.SN,
                    checktype = item?.value_type ?? 0,
                    index = detail.NumberIndex,
                    lowerlimit = detail.LowerLimit,
                    upperlimit = detail.UpperLimit,
                    range = (detail.LowerLimit.HasValue && detail.UpperLimit.HasValue) ?
                        Math.Round(detail.UpperLimit.Value - detail.LowerLimit.Value, 4).ToString() : "",
                    valuecategory = item?.value_category ?? 0,
                    item_range = (item?.range ?? 0).ToString()
                });
            }

            return new ObjectResult(res);
        }

        [HttpGet]
        public IActionResult GetCheckFile(string url)
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new BadRequestException(RequestEnum.ErrorFilePath);
            }

            if (url.ToLower().EndsWith(".zip") || url.ToLower().EndsWith(".dwg") || url.ToLower().EndsWith(".jpg") || url.ToLower().EndsWith(".eng"))
            {
                return new ObjectResult(new { content = "无法预览" });
            }

            var filename = url.Substring(url.IndexOf('/'));
            var fileSetting = Config<FileSettings>.Get();
            var path = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder);
            path += filename;
            if (!System.IO.File.Exists(path))
            {
                Logger.WriteLineError($"GetCheckFile from:{path} failed");
                throw new BadRequestException(RequestEnum.ErrorFilePath);
            }
            var data = System.IO.File.ReadAllLines(path);
            return new ObjectResult(new { data.Length, content = FileUtility.GetText(path) });
        }

        [HttpPost]
        public IActionResult BadIncomingData([FromBody]RequestBadIncomingData request)
        {
            var ret = new ResponseBadIncomingData();
            var pid = ProjectId;
            var invalid = (int)RowState.Invalid;
            var start = request.start;
            var end = request.end;
            var reject_status = (int)IncomingMaterialType.Rejection;
            var rework_status = (int)IncomingMaterialType.Rework;
            var sections = _machineAttributionRepository.GetSonLevelSections(request.section, pid).Select(f => f.id).ToList();
            if (!sections.Any())
            {
                sections.Add(request.section);
            }
            var materialIds = new List<int>();
            if(request.materialid.ToInt() != 0)
            {
                var material = _materialsRepository.Get(t => t.projectId == ProjectId && t.status == (int)RowState.Valid && t.id == request.materialid.ToInt());
                if (material != null)
                {
                    materialIds = _materialsRepository.GetList(t => t.projectId == ProjectId && t.status == (int)RowState.Valid && t.name == material.name).
                        Select(t => t.id).ToList();
                }
            }
            Expression<Func<siger_check_sn_trace_material, bool>> funCommon = f => f.projectid == pid && f.status != invalid && f.CreateTime >= start && f.CreateTime <= end && sections.Contains(f.SectionID);
            Expression<Func<siger_check_sn_trace_material, bool>> funProduct = f => true;
            if (request.product != 0)
            {
                funProduct = f => f.ProductID == request.product;
            }
            Expression<Func<siger_check_sn_trace_material, bool>> funMaterial = f => true;
            if (request.materialid.ToInt() != 0)
            {                                
                funMaterial = f => materialIds.Contains(f.MaterialID);
            }
            if (request.material != 0)
            {
                funProduct = f => f.MaterialID == request.material;
            }
            Expression<Func<siger_check_sn_trace_material, bool>> funSupplier = f => true;
            if (request.supplier != 0)
            {
                funSupplier = f => f.SupplierID == request.supplier;
            }
            var predicate = funCommon.And(funProduct).And(funMaterial).And(funSupplier);
            var data = _traceMaterialRepository.GetList(predicate).ToList();
            var xtype = request.x_type;
            if (request.type == 1)
            {
                var dates = DateTimeHelper.GetDateTimes(start, end, 0);
                if (xtype == 1 || xtype == 2 || xtype == 4 || xtype == 5)
                {
                    var dateList = new List<DateTime>();
                    foreach (var date in dates)
                    {
                        dateList.Add(DateTimeHelper.GetTimeStartByType(xtype, date));
                    }
                    dates = dateList.Distinct().ToList();
                }
                for (int i = 0; i < dates.Count; i++)
                {                    
                    var endTime = dates[i];
                    var startTime = dates[i];
                    if (xtype == 1 || xtype == 2 || xtype == 4 || xtype == 5)
                    {
                        startTime = DateTimeHelper.GetTimeStartByType(xtype, dates[i]);
                        endTime = DateTimeHelper.GetTimeEndByType(xtype, dates[i]).AddDays(1).AddMilliseconds(-1);
                        if (startTime < start)
                        {
                            startTime = start;
                        }
                        if (endTime > end)
                        {
                            endTime = end;
                        }
                    }
                    else
                    {
                        if (i < dates.Count - 1)
                        {
                            endTime = dates[i + 1].AddSeconds(-1);
                        }
                        else
                        {
                            endTime = end;
                        }
                    }
                    var spliceTime = DateTimeHelper.GetTimeStrByType(xtype, startTime);
                    ret.x1.Add(spliceTime);
                    var model = data.Where(f => f.status != 0 && f.CreateTime >= startTime && f.CreateTime < endTime).ToList();
                    var qty = model.Count(f => f.Result.Equals(reject_status.ToStr()) || f.Result.Equals(rework_status.ToStr()));
                    var total = model.Count;
                    ret.y1.Add(total);
                    ret.y2.Add(qty);
                    double rate = 0;
                    if (total != 0)
                    {
                        rate = qty / (double)total;
                    }
                    ret.y3.Add(Math.Round(rate * 100, 2));
                    ret.data.Add(new ResponseBadIncomingDataEx { defect_batch = qty, month = spliceTime, defect_rate = Math.Round(rate * 100, 2), incoming_batch = total });
                }
            }
            else if (request.type == 2)
            {

                var total = data.Count;
                data = data.Where(f => f.status != 0 && f.Result.Equals(reject_status.ToStr()) || f.Result.Equals(rework_status.ToStr())).ToList();
                if (data.Any())
                {
                    var supplierids = data.Select(s => s.SupplierID).Distinct().ToList();
                    var supplierdata = _contactsRepository.GetList(f => f.projectid == ProjectId && supplierids.Contains(f.id)).ToList();
                    foreach (var supplierid in supplierdata)
                    {
                        var suppliercount = data.Count(f => f.SupplierID == supplierid.id);
                        if (suppliercount >= 0)
                        {
                            var pm = Math.Round((double)suppliercount * 1000000 / (double)total, 0);
                            //ret.x1.Add(supplierid.name);
                            //ret.y3.Add(pm);
                            ret.data.Add(new ResponseBadIncomingDataEx { month = supplierid.enterprise_name, defect_rate = pm });
                        }
                    }
                    ret.data = ret.data.OrderByDescending(t => t.defect_rate).ToList();
                }
            }
            else if (request.type == 3)
            {
                data = data.Where(f => f.SupplierID != 0 && f.status != 0 && (f.Result.Equals(reject_status.ToStr()) || 
                    f.Result.Equals(rework_status.ToStr()))).ToList();
                var suppliers = data.Select(s => s.SupplierID).Distinct();
                var response = new List<ResponseBadIncomingData>();
                foreach (var supplierid in suppliers)
                {
                    var da = new ResponseBadIncomingData();

                    da.name = _contactsRepository.Get(f => f.id == supplierid)?.enterprise_name ?? "";
                    var traceids = data.Where(f => f.SupplierID == supplierid).Select(s => s.id).Distinct();
                    var details = _traceMaterialdetailRepository.GetList(f => f.projectid == pid && f.status != 0 && traceids.Contains(f.TraceID) && 
                        f.Result.ToUpper().Equals("NG"));

                    var itemCounts = from p in details
                                     group p by p.ItemID into g
                                     select new
                                     {
                                         g.Key,
                                         NumCounts = g.Count()
                                     };
                    var dataCounts = itemCounts.OrderByDescending(t => t.NumCounts).Take(3).ToList();

                    var inspectItems = _inspectStandard.GetList(t => dataCounts.Select(q => q.Key).Contains(t.id) && t.projectid == ProjectId &&
                        t.status == (int)RowState.Valid).ToList();
                    foreach (var itemData in dataCounts)
                    {
                        var item = inspectItems.FirstOrDefault(t => t.id == itemData.Key);
                        if(item == null)
                        {
                            continue;
                        }
                        da.x1.Add(item.item);
                        da.y1.Add(itemData.NumCounts);
                    }

                    response.Add(da);
                }
                return new ObjectResult(response);
            }
            if(request.type == 2)
            {
                var total_data = ret.data.Sum(t => t.defect_rate);
                int u = 1;
                double totalRate = 0;
                foreach (var item in ret.data)
                {
                    ret.x1.Add(item.month);
                    ret.y3.Add(item.defect_rate);
                    var rate = total_data > 0 ? Math.Round((item.defect_rate / total_data) * 100, 2) : 100;
                    totalRate += rate;
                    if (u == ret.data.Count)
                    {
                        ret.y4.Add(100);
                    }
                    else
                    {
                        ret.y4.Add(Math.Round(totalRate, 2));
                    }
                    u++;
                }
            }
            return new ObjectResult(ret);
        }

        [HttpGet]
        public IActionResult CheckIncomingSn(string sn)
        {
            var checkSnHelper = new CheckSnHelper();
            checkSnHelper.SplitBarcode(sn);
            var res = new ResponseCheckIncomingSn
            {
                partno = checkSnHelper.campoP,
                quantity = checkSnHelper.campoQ.Replace("\u001e\u0004\r", "").Trim().ToInt(),
                batchnumber = checkSnHelper.campoT
            };
            var material = _materialsRepository.Get(t => t.projectId == ProjectId && t.status == (int)RowState.Valid &&
                t.pn == res.partno);
            res.materialid = material?.id ?? 0;
            res.partname = material?.name ?? "";
            res.spec = material?.spec ?? "";
            return new ObjectResult(res);
        }

        [HttpGet]
        public IActionResult Delete(int id)
        {
            var data = _traceMaterialRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                t.id == id);
            if(data == null)
            {
                throw new BadRequestException(CommonEnum.DataNotNull);
            }

            if(DeleteData(data, true))
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            else
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="deleteTrace">是否删除trace</param>
        /// <returns></returns> 
        private bool DeleteData(siger_check_sn_trace_material data, bool deleteTrace)
        {
            var details = _traceMaterialdetailRepository.GetList(t => t.TraceID == data.id && t.projectid == ProjectId &&
                t.status == (int)RowState.Valid).ToList();
            var files = _traceFileRepository.GetList(t => t.trace_id == data.id && t.projectid == ProjectId &&
                t.status == (int)RowState.Valid && t.trace_type == (int)FileTraceType.InComingMaterial).ToList();

            if (deleteTrace)
            {
                data.status = (int)RowState.Invalid;
                _traceMaterialRepository.Update(data);
            }
            foreach (var detail in details)
            {
                detail.status = (int)RowState.Invalid;
                _traceMaterialdetailRepository.Update(detail);
            }
            foreach (var file in files)
            {
                file.status = (int)RowState.Invalid;
                _traceFileRepository.Update(file);
            }

            return _unitOfWork.Commit() > 0;
        }

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

            var result = req.result.ToInt();
            if (result <= 0)
            {
                throw new BadRequestException(RequestEnum.SelectCheckResult);
            }

            if (req.details == null || !req.details.Any())
            {
                throw new BadRequestException(RequestEnum.ParameterMiss);
            }

            if(req.details.Count == req.details.Max(t => t.index))
            {
                req.details = req.details.Where(t => !string.IsNullOrEmpty(t.sn)).ToList();
                if (!req.details.Any())
                {
                    throw new BadRequestException(RequestEnum.ParameterMiss);
                }
                var Sns = req.details.Where(t => !string.IsNullOrEmpty(t.sn)).ToList();
                foreach (var sn in Sns)
                {
                    if (Sns.Count(t => t == sn) > 1)
                    {
                        throw new BadRequestException(RequestEnum.SnDontRepeat);
                    }
                }
                if (!DeleteData(data, false))
                {
                    throw new BadRequestException(CommonEnum.Fail);
                }
                var insertDetailList = new List<siger_check_sn_trace_material_detail>();
                foreach (var detail in req.details)
                {
                    insertDetailList.Add(new siger_check_sn_trace_material_detail
                    {
                        TraceID = data.id,
                        ItemID = 0,
                        ItemName = "",
                        Result = "",
                        Value = null,
                        UserID = data.UserID,
                        CreateTime = data.CreateTime,
                        projectid = ProjectId,
                        SN = detail.sn ?? "",
                        NumberIndex = detail.index
                    });
                }
                _traceMaterialdetailRepository.Insert(insertDetailList);
                SaveFiles(req.files, req.images, data.id);
                data.Result = req.result;
                _traceMaterialRepository.Update(data);
                if (_unitOfWork.Commit() > 0)
                {
                    return new ObjectResult(CommonEnum.Succefull);
                }
                else
                {
                    throw new BadRequestException(CommonEnum.Fail);
                }
            }
            else
            {
                var indexs = req.details.Select(t => t.index).Distinct().ToList();
                var items = _inspectStandard.GetList(t => req.details.Select(q => q.itemid).Contains(t.id)).ToList();
                foreach (var index in indexs)
                {
                    var Sns = new List<string>();
                    var traceDetails = req.details.Where(t => t.index == index).OrderBy(t => t.index).ToList();
                    if (traceDetails.Any())
                    {
                        traceDetails.RemoveAt(0);
                        if (!string.IsNullOrEmpty(traceDetails.FirstOrDefault().sn))
                        {
                            Sns.Add(traceDetails.FirstOrDefault().sn);
                        }
                        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);
                            }
                        }
                    }
                    foreach (var sn in Sns)
                    {
                        if (Sns.Count(t => t == sn) > 1)
                        {
                            throw new BadRequestException(RequestEnum.SnDontRepeat);
                        }
                    }
                }
                if (!DeleteData(data, false))
                {
                    throw new BadRequestException(CommonEnum.Fail);
                }
                SaveFiles(req.files, req.images, data.id);
                var insertDetailList = new List<siger_check_sn_trace_material_detail>();
                foreach (var index in indexs)
                {
                    var traceDetails = req.details.Where(t => t.index == index).OrderBy(t => t.index).ToList();
                    if (traceDetails.Any())
                    {
                        traceDetails.RemoveAt(0);
                    }                        
                    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 siger_check_sn_trace_material_detail
                            {
                                TraceID = data.id,
                                ItemID = item.id,
                                ItemName = item.item,
                                Result = detail.result,
                                Value = null,
                                UserID = data.UserID,
                                CreateTime = data.CreateTime,
                                projectid = ProjectId,
                                SN = detail.sn ?? "",
                                NumberIndex = detail.index
                            });
                        }
                        else if (item.value_type == (int)ValueTypeStatus.V)
                        {
                            if (detail.value == null)
                            {
                                continue;
                            }
                            if (item.value_category == (int)ValueCategory.Maxmin && !detail.upperlimit.HasValue && !detail.lowerlimit.HasValue)
                            {
                                continue;
                            }
                            var detailResult = "";
                            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 siger_check_sn_trace_material_detail
                            {
                                TraceID = data.id,
                                ItemID = item.id,
                                ItemName = item.item,
                                Result = detailResult,
                                Value = detail.value,
                                UserID = data.UserID,
                                CreateTime = data.CreateTime,
                                projectid = ProjectId,
                                SN = detail.sn ?? "",
                                NumberIndex = detail.index,
                                UpperLimit = detail.upperlimit,
                                LowerLimit = detail.lowerlimit,
                            });
                        }
                    }
                }
                _traceMaterialdetailRepository.Insert(insertDetailList);
                data.Result = req.result;
                _traceMaterialRepository.Update(data);
                if (_unitOfWork.Commit() > 0)
                {
                    return new ObjectResult(CommonEnum.Succefull);
                }
                else
                {
                    throw new BadRequestException(CommonEnum.Fail);
                }
            }
        }

        /// <summary>
        /// 修改时获取数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetUpdateDetails(int id)
        {
            var data = _traceMaterialRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid && t.id == id);
            if (data == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var res = new ResponseGetUpdateDetails
            {
                result = data.Result.ToInt()
            };

            var fileList = _traceFileRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                t.trace_type == (int)FileTraceType.InComingMaterial && t.trace_id == data.id).ToList();
            var images = fileList.Where(t => t.file_type == (int)TraceFileType.Image).ToList();
            var files = fileList.Where(t => t.file_type == (int)TraceFileType.File).ToList();
            foreach (var image in images)
            {
                res.images.Add(new UploadFileModel
                {
                    url = image.url,
                    name = image.name,
                    size = image.size,
                });
            }
            foreach (var file in files)
            {
                res.files.Add(new UploadFileModel
                {
                    url = file.url,
                    name = file.name,
                    size = file.size,
                });
            }           
            
            var details = _traceMaterialdetailRepository.GetList(t => t.projectid == ProjectId &&
                t.status == (int)RowState.Valid && t.TraceID == data.id).ToList();
            var items = _inspectStandard.GetList(t => details.Select(q => q.ItemID).Contains(t.id)).ToList();
            foreach (var detail in details)
            {
                var item = items.FirstOrDefault(t => t.id == detail.ItemID);
                res.details.Add(new IncomingMaterialDetails
                {
                    id = detail.id,
                    itemid = detail.ItemID,
                    itmename = item?.item ?? detail.ItemName,
                    max_value = item?.max_value ?? 0,
                    min_value = item?.min_value ?? 0,
                    standard = item?.standard ?? "",
                    result = detail.Result,
                    value = detail.Value,
                    sn = detail.SN,
                    checktype = item?.value_type ?? 0,
                    index = detail.NumberIndex,
                    lowerlimit = detail.LowerLimit,
                    upperlimit = detail.UpperLimit,
                    range = (detail.LowerLimit.HasValue && detail.UpperLimit.HasValue) ?
                        (detail.UpperLimit.Value - detail.LowerLimit.Value).ToString() : "",
                    valuecategory = item?.value_category ?? 0,
                });
            }

            return new ObjectResult(res);
        }

        [HttpGet]
        public IActionResult GetCheckSuppliers(string materialid, string materialNameId)
        {
            var supplierIds = new List<int>();
            var materialIds = new List<int>();
            if(materialNameId.ToInt() > 0)
            {
                var material = _materialsRepository.Get(t => t.projectId == ProjectId && t.status == (int)RowState.Valid &&
                    t.id == materialNameId.ToInt());
                if(material != null)
                {
                    materialIds = _materialsRepository.GetList(t => t.projectId == ProjectId && t.status == (int)RowState.Valid &&
                        t.name == material.name).Select(t=>t.id).ToList();
                }
            }
            var traceData = _traceMaterialRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                t.SupplierID > 0);
            if(materialid.ToInt() > 0)
            {
                traceData = traceData.Where(t => t.MaterialID == materialid.ToInt());
            }
            if(materialNameId.ToInt() > 0)
            {
                traceData = traceData.Where(t => materialIds.Contains(t.MaterialID));
            }
            supplierIds = traceData.Select(t => t.SupplierID).Distinct().ToList();
            var suppliers = _contactsRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                supplierIds.Contains(t.id)).Select(q => new
                {
                    q.id,
                    q.name,
                    q.enterprise_name
                }).ToList();
            return new ObjectResult(suppliers);
        }

        [HttpGet]
        public IActionResult GetCheckMaterials(string supplierid, string sectionid, string materialNameId, string distinct = "0")
        {
            var materialIds = new List<int>();
            var sectionIds = new List<int>();
            if (sectionid.ToInt() > 0)
            {
                sectionIds = _levelSectionRepository.GetLevelSectionIds(sectionid.ToInt(), ProjectId).ToList();
            }
            var materialNameIds = new List<int>();
            if(materialNameId.ToInt() > 0)
            {
                var material = _materialsRepository.Get(t => t.projectId == ProjectId && t.status == (int)RowState.Valid &&
                    t.id == materialNameId.ToInt());
                if(material != null)
                {
                    materialNameIds = _materialsRepository.GetList(t => t.projectId == ProjectId && t.status == (int)RowState.Valid &&
                        t.name == material.name).Select(t => t.id).ToList();
                }
            }
            var traceData = _traceMaterialRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid);
            if(supplierid.ToInt() > 0)
            {
                traceData = traceData.Where(t => t.SupplierID == supplierid.ToInt());
            }
            if(sectionid.ToInt() > 0)
            {
                traceData = traceData.Where(t => sectionIds.Contains(t.SectionID));
            }
            if(materialNameId.ToInt() > 0)
            {
                traceData = traceData.Where(t => materialNameIds.Contains(t.MaterialID));
            }
            materialIds = traceData.Select(t => t.MaterialID).Distinct().ToList();
            var res = _materialsRepository.GetList(t => t.projectId == ProjectId && t.status == (int)RowState.Valid &&
                materialIds.Contains(t.id)).Select(q => new
                {
                    q.id,
                    q.name,
                    q.spec,
                    q.pn
                }).ToList();

            res = distinct.ToInt() > 0 ? res.GroupBy(t => t.name).Select(t => t.FirstOrDefault()).ToList() : res;
            return new ObjectResult(res);
        }
    }
}