using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Redis.RedisEntities;
using Siger.Middlelayer.Repository.Data;
using Siger.Middlelayer.Share.Models;
using Siger.Middlelayer.ToolRepository.Entities;
using Siger.Middlelayer.ToolRepository.Repositories.Interface;
using Siger.Middlelayer.ToolRepository.Request;
using Siger.Middlelayer.ToolRepository.Response;
using Siger.Middlelayer.Utility.ImportEntities;
using System.Threading.Tasks;
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
using NPOI.SS.Formula.Functions;
using System.Linq.Expressions;
using System.ComponentModel;
using Siger.Middlelayer.Repository.Extensions;

namespace Siger.Middlelayer.ToolRepository.Repositories
{
    internal class SigerProjectToolCutterLocationTrueRepository :
        ApiToolRepositoryBase<SigerProjectToolCutterLocationTrue>, ISigerProjectToolCutterLocationTrueRepository
    {
        ApiToolDbContext apiToolDbContext;

        public SigerProjectToolCutterLocationTrueRepository(ApiToolDbContext context) : base(context)
        {
            apiToolDbContext = context;
        }

        public IEnumerable<CutterLocationAlarmSetting> GetCutterLocationAlarmSetting(int sectionId, int projectId, int page, int pageSize, out int toalCount)
        {
            var mids = GetMachineIds(sectionId, projectId);

            var ptcl = apiToolDbContext.siger_project_tool_cutter_location_true.Where(f => f.is_processing_program != (int)ProcessProgram.NoConfig &&
                                                                                f.status == (int)RowState.Valid);
            //var queryData= from mid in mids
            //               join m in apiToolDbContext.siger_project_machine on mid.MachineId equals m.id into Tbl from q in Tbl
            //               join ts in apiToolDbContext.siger_project_tool_spindle_true on q.s equals ts.

            var data = (from tcl in ptcl
                        join ts in apiToolDbContext.siger_project_tool_spindle_true
                        on tcl.spindleid equals ts.id
                        join m in apiToolDbContext.siger_project_machine
                        on ts.equipid equals m.id
                        where mids.Contains(m.id) && ts.status == (int)RowState.Valid && m.status == (int)RowState.Valid
                        orderby m.title, ts.name, tcl.name, tcl.programno
                        select new CutterLocationAlarmSetting
                        {
                            id = tcl.id,
                            cutter_location_name = tcl.name,
                            programno = tcl.programno,
                            spindle_name = ts.name,
                            machine_id = m.id,
                            machine_name = m.title,
                            machine_code = m.code,
                            alert_condition_num = apiToolDbContext.siger_project_tool_alert_condition.Count(f => f.cutterlocationid == tcl.id &&
                                                                         f.is_open == 1 &&
                                                                         f.status == (int)RowState.Valid)
                        });
            toalCount = data.Count();
            var result = data.Skip((page - 1) * pageSize).Take(pageSize).ToList();
            if (!result.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            foreach (var f in result)
            {
                var res = apiToolDbContext.siger_project_tool_alert_condition.Where(q => q.cutterlocationid == f.id &&
                                                                           q.is_open == 1 &&
                                                                           q.status == (int)RowState.Valid);
                if (!res.Any())
                {
                    f.createtime = "-";
                    f.content = "-";
                    continue;
                }
                List<int> arr = new List<int>();
                foreach (var item in res)
                {
                    if (item.condition_type == 1)
                    {
                        arr.Add(item.condition_param);
                    }
                    else if (item.condition_type == 2)
                    {
                        arr.Add(item.condition_param + 8);
                    }
                    f.createtime = (item.createtime != 0) ? UnixTimeHelper.ConvertIntDateTime(item.createtime) : "-";
                }
                //报警规则排序
                arr.Sort();
                f.content = string.Join(",", arr);
            };
            return result;
        }

        public bool UpdateAutoStudy(List<int> spindleID, string programNo, int autoStudy)
        {
            var data = apiToolDbContext.siger_project_tool_cutter_location_true.Where(f => spindleID.Contains(f.spindleid) && f.programno == programNo && f.status == (int)RowState.Valid).ToList();

            foreach (var item in data)
            {
                item.auto_study = autoStudy;
            }
            apiToolDbContext.siger_project_tool_cutter_location_true.UpdateRange(data);
            if (apiToolDbContext.SaveChanges() > 0)
                return true;
            else
                return false;
        }

        public List<string> GetToolTypes(int projectId, int sectionId)
        {
            var mids = GetMachineIds(sectionId, projectId);
            if (!mids.Any())
            {
                return new List<string>();
            }
            var data = (from clt in apiToolDbContext.siger_project_tool_cutter_location_true
                        join t in apiToolDbContext.siger_project_tool on clt.toolid equals t.id
                        join st in apiToolDbContext.siger_project_tool_spindle_true on clt.spindleid equals st.id
                        join m in apiToolDbContext.siger_project_machine on st.equipid equals m.id
                        where m.status == (int)RowState.Valid && t.status == (int)RowState.Valid && clt.status == (int)RowState.Valid &&
                        m.projectid == projectId && mids.Contains(m.id)
                        select t.name).Distinct();
            if (data.Any())
            {
                return data.ToList();
            }

            return new List<string>();
        }

        public List<ResponseToolLifeList> GetToolLifeList(int projectId, int sectionId)
        {
            var mids = GetMachineIds(sectionId, projectId);
            var cutterLocationList = from tcl in apiToolDbContext.siger_project_tool_cutter_location_true
                                     join ts in apiToolDbContext.siger_project_tool_spindle_true on tcl.spindleid equals ts.id
                                     join m in apiToolDbContext.siger_project_machine on ts.equipid equals m.id
                                     join t in apiToolDbContext.siger_project_tool on tcl.toolid equals t.id
                                     where mids.Contains(m.id) &&
                                           //tcl.ratedlife > 0 &&
                                           tcl.status == (int)RowState.Valid &&
                                           ts.status == (int)RowState.Valid && m.status == (int)RowState.Valid &&
                                           tcl.is_processing_program != (int)ProcessProgram.NoConfig
                                     select new ResponseToolLifeList
                                     {
                                         id = tcl.id,
                                         machine_code = m.code,
                                         machine_name = m.title,
                                         spindle_name = ts.name,
                                         cutter_location_name = tcl.name,
                                         tool_name = t.name,
                                         drawingcode = t.drawingcode,
                                         description = t.description,
                                         ratedlife = tcl.ratedlife,
                                         programno = tcl.programno,
                                         subprogramno = tcl.subprogramno ?? "",
                                         machineId = m.id,
                                         IsProcess = tcl.is_processing_program
                                     };
            return cutterLocationList.AsNoTracking().ToList();
        }

        public ResponseToolLifeEntity GetToolLifeEntity(int id)
        {
            var cutterLocationList = from tcl in apiToolDbContext.siger_project_tool_cutter_location_true
                                     join ts in apiToolDbContext.siger_project_tool_spindle_true on tcl.spindleid equals ts.id
                                     join m in apiToolDbContext.siger_project_machine on ts.equipid equals m.id
                                     join t in apiToolDbContext.siger_project_tool on tcl.toolid equals t.id
                                     into tmp1
                                     from tool in tmp1.DefaultIfEmpty()

                                     where tcl.id == id && tcl.status == (int)RowState.Valid &&
                                           ts.status == (int)RowState.Valid && m.status == (int)RowState.Valid
                                           && m.category == (int)MachineCategory.NC
                                     select new ResponseToolLifeEntity
                                     {
                                         machine_code = m.code,
                                         machine_name = m.title,
                                         spindle_name = ts.name,
                                         cutter_location_name = tcl.name,
                                         tool_name = tool == null ? "" : tool.name,
                                         drawingcode = tool == null ? "" : tool.drawingcode,
                                         ratedlife = tcl.ratedlife,
                                         programno = tcl.programno,
                                         subprogramno = tcl.subprogramno,
                                         machine_Id = m.id,

                                         IsProcess = tcl.is_processing_program
                                     };
            return cutterLocationList.FirstOrDefault();
        }

        public ToolInfo GetChangeRecordOtherInfo(int projectId, int companyId, int machine_id, int spindle_id, string cutter_location_name)
        {

            var cutterLocation = from tcl in apiToolDbContext.siger_project_tool_cutter_location_true
                                 join ts in apiToolDbContext.siger_project_tool_spindle_true on tcl.spindleid equals ts.id
                                 join tool in apiToolDbContext.siger_project_tool on tcl.toolid equals tool.id into temp
                                 from tools in temp.DefaultIfEmpty()
                                 where tcl.spindleid == spindle_id && tcl.name == cutter_location_name &&
                                       ts.equipid == machine_id &&
                                       tcl.status == (int)RowState.Valid &&
                                       ts.status == (int)RowState.Valid &&
                                       tcl.is_processing_program != (int)ProcessProgram.NoConfig
                                 orderby tcl.update_time descending
                                 select new ToolInfo
                                 {
                                     tool_name = tools == null ? "" : tools.name,
                                     drawingcode = tools == null ? "" : tools.drawingcode,
                                     supplier = tools == null ? "" : tools.supplier,
                                     ratedlife = tcl.ratedlife,
                                     programno = tcl.is_processing_program == (int)ProcessProgram.MainProgram
                                         ? tcl.programno
                                         : tcl.subprogramno,
                                 };

            return cutterLocation.FirstOrDefault();

            //var cutterLocation = from tcl in apiToolDbContext.siger_project_tool_cutter_location_true
            //                     join ts in apiToolDbContext.siger_project_tool_spindle_true on tcl.spindleid equals ts.id
            //                     join m in apiToolDbContext.siger_project_machine on ts.equipid equals m.id
            //                     join tool in apiToolDbContext.siger_project_tool on tcl.toolid equals tool.id
            //                     where m.id == machine_id && tcl.spindleid == spindle_id && tcl.name == cutter_location_name &&
            //                           tcl.status == (int)RowState.Valid && tool.status == (int)RowState.Valid &&
            //                           ts.status == (int)RowState.Valid && m.status == (int)RowState.Valid &&
            //                           tool.projectid == projectId && m.projectid == projectId &&
            //                           tcl.is_processing_program != (int)ProcessProgram.NoConfig
            //                     orderby tcl.update_time descending
            //                     select new ToolInfo
            //                     {
            //                         tool_name = tool.name,
            //                         drawingcode = tool.drawingcode,
            //                         supplier = tool.supplier,
            //                         ratedlife = tcl.ratedlife,
            //                         programno = tcl.is_processing_program == (int)ProcessProgram.MainProgram
            //                             ? tcl.programno
            //                             : tcl.subprogramno,
            //                     };

            //return cutterLocation.FirstOrDefault();
        }

        public bool SetCutterLocationAlarmSetting(int projectId)
        {
            var data = new List<SigerProjectToolAlertCondition>();
            var mids = GetMachineIds(0, projectId);
            var cutterLocationList = (from tcl in apiToolDbContext.siger_project_tool_cutter_location_true
                                      join ts in apiToolDbContext.siger_project_tool_spindle_true on tcl.spindleid equals ts.id
                                      into tmp1
                                      from t1 in tmp1.DefaultIfEmpty()
                                      join m in apiToolDbContext.siger_project_machine.DefaultIfEmpty()
                                      on t1.equipid equals m.id
                                      where mids.Contains(m.id) &&
                                      tcl.is_processing_program != (int)ProcessProgram.NoConfig &&
                                      tcl.status == (int)RowState.Valid &&
                                      t1.status == (int)RowState.Valid &&
                                      m.status == (int)RowState.Valid
                                      orderby m.title, t1.name, tcl.name, tcl.programno
                                      select tcl.id).Distinct();
            if (cutterLocationList.Count() != 0)
            {
                var alerts = apiToolDbContext.siger_alert_condition.Where(f => f.status == (int)RowState.Valid);
                if (alerts.Count() != 0)
                {
                    foreach (var v in alerts)
                    {
                        foreach (var vv in cutterLocationList)
                        {
                            int.TryParse(v.condition_param, out int condition_param);
                            int.TryParse(v.condition_type, out int condition_type);
                            data.Add(new SigerProjectToolAlertCondition()
                            {
                                cutterlocationid = vv,
                                condition_param = condition_param,
                                condition_type = condition_type,
                                is_open = v.is_open,
                                m = v.default_m,
                                k = v.Default,
                                status = v.status,
                                createtime = (int)UnixTimeHelper.ConvertDataTimeLong(DateTime.Now),
                            });
                        }
                    }
                }
            }
            if (data.Count != 0)
            {
                //先清空数据，在添加
                var entitys = apiToolDbContext.siger_project_tool_alert_condition;
                //清空原来的配置
                apiToolDbContext.siger_project_tool_alert_condition.RemoveRange(entitys);
                //新增配置
                foreach (var item in data)
                {
                    apiToolDbContext.siger_project_tool_alert_condition.Add(item);
                }
                if (apiToolDbContext.SaveChanges() > 0)
                {
                    return true;
                }
            }
            throw new BadRequestException(CommonEnum.ConfigError);
        }

        public List<SigerProjectTool> GetToolList(int sectionId, int projectId, string tooltype, string toolfilter, string brand, int count)
        {
            //var data = new List<SigerProjectTool>();
            //data = (from clt in apiToolDbContext.siger_project_tool_cutter_location_true
            //    join st in apiToolDbContext.siger_project_tool_spindle_true on clt.spindleid equals st.id
            //        into tmp1
            //    from t1 in tmp1.DefaultIfEmpty()
            //    join m in apiToolDbContext.siger_project_machine on t1.equipid equals m.id
            //        into tmp2
            //    from t2 in tmp2.DefaultIfEmpty()
            //    join t in apiToolDbContext.siger_project_tool on clt.toolid equals t.id
            //        into re
            //    from r in re.DefaultIfEmpty()
            //    where t2.projectid == projectId && r.status == (int) RowState.Valid &&
            //          t1.status == (int) RowState.Valid && t2.status == (int) RowState.Valid &&
            //          mids.Contains(t2.id)
            //    select r).Distinct().ToList();

            var data = (from q in apiToolDbContext.siger_project_tool
                        where q.projectid == projectId && q.status == (int)RowState.Valid
                        select q).ToList();
            if (!string.IsNullOrEmpty(tooltype) && tooltype != "0")
            {
                data = data.Where(f => f.name.Contains(tooltype)).ToList();
            }
            if (!string.IsNullOrEmpty(toolfilter))
            {
                data = data.Where(f => f.drawingcode.Contains(toolfilter) || f.name.Contains(toolfilter) || f.brand.Contains(toolfilter)).ToList();
            }
            if (!string.IsNullOrEmpty(brand))
            {
                data = data.Where(f => f.brand.Contains(brand)).ToList();
            }
            if (count == 0)
            {
                return data;
            }
            else
            {
                return data.Take(count).ToList();
            }
        }

        public List<SigerProjectTool> GetToolList(RequestToolList request, int projectid)
        {
            var query = apiToolDbContext.siger_project_tool.Where(f => f.projectid == projectid && f.status != 0);
            Expression<Func<SigerProjectTool, bool>> funTool = f => true;
            if (!string.IsNullOrEmpty(request.toolfilter))
            {
                funTool = f => f.drawingcode.Contains(request.toolfilter) || f.name.Contains(request.toolfilter) || f.brand.Contains(request.toolfilter);
            }
            Expression<Func<SigerProjectTool, bool>> funToolType = f => true;
            if (!string.IsNullOrEmpty(request.tooltype))
            {
                funToolType = f => f.name.Contains(request.tooltype);
            }
            Expression<Func<SigerProjectTool, bool>> funBrand = f => true;
            if (!string.IsNullOrEmpty(request.brand))
            {
                funBrand = f => f.brand.Contains(request.brand);
            }
            Expression<Func<SigerProjectTool, bool>> funSection = f => true;
            if (!string.IsNullOrEmpty(request.section))
            {
                var mids = GetMachineIds(request.section.ToInt(), projectid);

                var toolMachineQuery = from clt in apiToolDbContext.siger_project_tool_cutter_location_true
                                      join st in apiToolDbContext.siger_project_tool_spindle_true on clt.spindleid equals st.id
                                          into tmp1
                                      from t1 in tmp1.DefaultIfEmpty()
                                      join m in apiToolDbContext.siger_project_machine on t1.equipid equals m.id
                                          into tmp2
                                      from t2 in tmp2.DefaultIfEmpty()
                                      where mids.Contains(t2.id)
                                      select clt.toolid;
                var tooids = toolMachineQuery.Select(s=>s.ToStr()).Where(f=>!string.IsNullOrEmpty(f)).Distinct().ToList();
                funSection = f => tooids.Contains(f.id.ToStr());
            }
            var predicate = funTool.And(funToolType).And(funBrand).And(funSection);
            if (string.IsNullOrEmpty(request.count) || request.count.ToInt() == 0)
            {
                return query.Where(predicate).OrderBy(o => o.id).AsNoTracking().ToList();
            }
            else
            {
                return query.Where(predicate).OrderBy(o => o.id).Take(request.count.ToInt()).AsNoTracking().ToList();
            }
        }

        public List<MachineData> GetMachineList(string machinefilter, int projectId, int count)
        {
            var result = from lsm in apiToolDbContext.siger_project_machine_attribution
                         join m in apiToolDbContext.siger_project_machine on lsm.machine equals m.id
                         where lsm.status == (int)RowState.Valid && m.status == (int)RowState.Valid
                                                                  && m.projectid == projectId && m.category == (int)MachineCategory.NC
                         select new MachineData
                         {
                             section_id = lsm.station,
                             machine_id = m.id,
                             machine_code = m.code,
                             machine_name = m.title
                         };
            var machines = result.ToList();
            if (!string.IsNullOrWhiteSpace(machinefilter))
            {
                machines = machines.Where(q => q.machine_code.Contains(machinefilter) || q.machine_name.Contains(machinefilter)).ToList();
            }
            if (count == 0)
            {
                return machines;
            }
            else
            {
                return machines.Take(count).ToList();
            }
        }

        public List<ProductData> GetProductList(string productfilter, int projectId, int count)
        {
            var result = new List<ProductData>();

            var products =
                apiToolDbContext.siger_project_product.Where(q =>
                    q.projectid == projectId && q.status == (int)RowState.Valid).ToList();

            if (!string.IsNullOrWhiteSpace(productfilter))
            {
                products = products.Where(q => q.code.Contains(productfilter) || q.name.Contains(productfilter)).ToList();
            }

            foreach (var sigerProjectProduct in products)
            {
                result.Add(new ProductData
                {
                    drawingcode = sigerProjectProduct.drawingcode,
                    name = sigerProjectProduct.code + "-" + sigerProjectProduct.name,
                    id = sigerProjectProduct.id
                });
            }
            if (count == 0)
            {
                return result;
            }
            else
            {
                return result.Take(count).ToList();
            }
        }

        public int AddConfigCutterLocation(RequestToolCutterLocationAdd request)
        {
            var names = request.cutter_location_name;
            var query = from tcl in apiToolDbContext.siger_project_tool_cutter_location_true
                        join sp in apiToolDbContext.siger_project_tool_spindle_true on tcl.spindleid equals sp.id
                        where tcl.status == (int)RowState.Valid && sp.status == (int)RowState.Valid
                              && sp.equipid == request.mid && names.Contains(tcl.name)
                              && sp.name == request.spindle_name
                              && ((tcl.is_processing_program == (int)ProcessProgram.MainProgram && tcl.programno == request.programno)
                                    || (tcl.is_processing_program == (int)ProcessProgram.ChildProgram && tcl.subprogramno == request.programno))
                        select tcl;
            if (query.FirstOrDefault() != null)
            {
                throw new ServerException(600177);
            }
            try
            {
                for (var i = 0; i < names.Count(); i++)
                {
                    int splindleId;
                    var splindleEntity = apiToolDbContext.siger_project_tool_spindle_true.FirstOrDefault(q =>
                        q.equipid == request.mid
                        && q.name == request.spindle_name
                        && q.status == (int)RowState.Valid);
                    if (splindleEntity != null)
                    {
                        splindleId = splindleEntity.id;
                    }
                    else
                    {
                        var splindle = new SigerProjectToolSpindleTrue
                        {
                            status = (int)RowState.Valid,
                            create_time = UnixTimeHelper.GetNow(),
                            update_time = UnixTimeHelper.GetNow(),
                            equipid = request.mid,
                            name = request.spindle_name,
                            productid = request.product_id
                        };
                        apiToolDbContext.siger_project_tool_spindle_true.Add(splindle);
                        apiToolDbContext.SaveChanges();
                        splindleId = splindle.id;
                    }
                    var cutterQuery = from tcl in apiToolDbContext.siger_project_tool_cutter_location_true
                                      join sp in apiToolDbContext.siger_project_tool_spindle_true on tcl.spindleid equals sp.id
                                      where tcl.status == (int)RowState.Valid && sp.status == (int)RowState.Valid
                                                                              && sp.equipid == request.mid && names[i] == tcl.name
                                                                              && tcl.spindleid == splindleId && tcl.is_processing_program == (int)ProcessProgram.NoConfig
                                                                              && (tcl.programno == request.programno || tcl.subprogramno == request.programno)
                                      select tcl;
                    var cutter = cutterQuery.FirstOrDefault();
                    if (cutter == null)
                    {
                        var entity = new SigerProjectToolCutterLocationTrue
                        {
                            status = (int)RowState.Valid,
                            create_time = UnixTimeHelper.GetNow(),
                            update_time = UnixTimeHelper.GetNow(),
                            auto_study = 1,
                            program_type = 1,
                            programno = request.programno,
                            subprogramno = "",
                            is_processing_program = (int)ProcessProgram.MainProgram,
                            spindleid = splindleId,
                            productid = request.product_id,
                            toolid = request.tool_id.Length == 0 ? 0 : request.tool_id[i].ToInt(),
                            name = request.cutter_location_name.Length == 0 ? "" : request.cutter_location_name[i],
                            ratedlife = request.ratedlife.Length == 0 ? 0 : request.ratedlife[i].ToInt(),
                            is_identical_collection = 0,
                            type = request.type[i],
                        };
                        if (request.coefficent != null)
                        {
                            entity.coefficent = request.coefficent[i];
                        }
                        apiToolDbContext.siger_project_tool_cutter_location_true.Add(entity);
                        apiToolDbContext.SaveChanges();
                    }
                    else
                    {
                        cutter.is_identical_collection = 1;
                        cutter.productid = request.product_id;
                        cutter.update_time = UnixTimeHelper.GetNow();
                        cutter.ratedlife = request.ratedlife[i].ToInt();
                        cutter.toolid = request.tool_id[i].ToInt();
                        cutter.type = request.type[i];
                        if (cutter.programno == request.programno)
                        {
                            cutter.is_processing_program = (int)ProcessProgram.MainProgram;
                        }
                        else
                        {
                            cutter.is_processing_program = (int)ProcessProgram.ChildProgram;
                        }
                        apiToolDbContext.siger_project_tool_cutter_location_true.Update(cutter);
                        apiToolDbContext.SaveChanges();
                    }
                }
            }
            catch
            {
                return 0;
            }
            return 1;
        }

        public List<ResponseToolConfigInfo> ExportToolConfigInfo(string programNo, int sectionId, int projectId)
        {
            var mids = GetMachineIds(sectionId, projectId);
            var tootal = from tcl in apiToolDbContext.siger_project_tool_cutter_location_true
                         join ts in apiToolDbContext.siger_project_tool_spindle_true on tcl.spindleid equals ts.id
                         join m in apiToolDbContext.siger_project_machine on ts.equipid equals m.id
                         join t in apiToolDbContext.siger_project_tool on tcl.toolid equals t.id into ttemp
                         from tt in ttemp.DefaultIfEmpty()
                         join p in apiToolDbContext.siger_project_product on tcl.productid equals p.id into ptemp
                         from pp in ptemp.DefaultIfEmpty()
                         where mids.Contains(ts.equipid) && m.projectid == projectId && tcl.status == (int)RowState.Valid && ts.status == (int)RowState.Valid &&
                         m.status == (int)RowState.Valid
                         && tcl.is_processing_program != (int)ProcessProgram.NoConfig
                         orderby tcl.is_identical_collection, tcl.update_time descending
                         select new ResponseToolConfigInfo
                         {
                             id = tcl.id,
                             machine_name = m.title,
                             machine_code = m.code,
                             spindle_name = ts.name,
                             cutter_location_name = tcl.name,
                             programno = tcl.is_processing_program == 1 ? tcl.programno : tcl.subprogramno,
                             is_identical_collection = tcl.is_identical_collection,
                             cutter_location_alias = tcl.cutter_location_alias,
                             ratedlife = tcl.ratedlife.ToString(),
                             tool_name = tt == null ? "Na" : tt.name,
                             drawingcode = tt == null ? "Na" : tt.drawingcode,
                             subprogramno = tcl.subprogramno,
                             productdrawingcode = pp == null ? "Na" : pp.drawingcode,
                             type = tcl.type,
                             coefficent= tcl.coefficent
                         };
            if (!string.IsNullOrEmpty(programNo))
            {
                tootal = tootal.Where(f => f.programno == programNo || f.subprogramno == programNo);
            }
            return tootal.ToList();
        }

        public ToolImportResult ImportToolLocations(IEnumerable<ToolLocationList> tools, int projectId)
        {
            var errors = new List<string>();
            var rowIndex = 1;
            var machineIds = new List<int>();
            var productIds = new List<int>();
            var toolIds = new List<int>();
            string pattern = @"^\d*$";

            foreach (var toolLocation in tools)
            {
                rowIndex++;
                if (toolLocation.Coefficent < 0 && !System.Text.RegularExpressions.Regex.IsMatch(toolLocation.Coefficent.ToStr(), pattern))
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.ParameterMiss}");
                }
                var machineEntity = apiToolDbContext.siger_project_machine.FirstOrDefault(q =>
                    q.code == toolLocation.Code && q.status == (int)RowState.Valid && q.projectid == projectId && q.category == (int)MachineCategory.NC);
                if (machineEntity == null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.MachineNotFound}");
                }
                else
                {
                    machineIds.Add(machineEntity.id);
                }

                var product = apiToolDbContext.siger_project_product.FirstOrDefault(q =>
                    q.drawingcode == toolLocation.DrawingCode && q.status == (int)RowState.Valid && q.projectid == projectId);

                //if (product == null)
                //{
                //    errors.Add($"{rowIndex},{(int)RequestEnum.ProductNotFound}");
                //}
                //else
                //{
                //    productIds.Add(product.id);
                //}
                if (product != null)
                {
                    productIds.Add(product.id);
                }
                var toolInfo = apiToolDbContext.siger_project_tool.FirstOrDefault(q =>
                    q.drawingcode == toolLocation.ToolDrawingCode && q.status == (int)RowState.Valid
                                                                  && q.projectid == projectId);
                //if (toolInfo == null)
                //{
                //    errors.Add($"{rowIndex},{(int)RequestEnum.ToolNotFound}");
                //}
                //else
                //{
                //    toolIds.Add(toolInfo.id);
                //}
                if (toolInfo != null)
                {
                    toolIds.Add(toolInfo.id);
                }

                if (errors.Any())
                {
                    return new ToolImportResult(0, string.Join(";", errors), null);
                }
            }

            var toolInfoes = tools.ToList();
            var toolImportInfo = new List<ToolImportInfo>();
            try
            {
                for (var i = 0; i < toolInfoes.Count; i++)
                {
                    int _prductid = 0, _toolid = 0;
                    if (productIds.Any())
                    {
                        _prductid = productIds[i];
                    }
                    if (toolIds.Any())
                    {
                        _toolid = toolIds[i];
                    }
                    var toolLocation = toolInfoes[i];
                    //先插入主轴
                    int splindleId;
                    var splindleEntity = apiToolDbContext.siger_project_tool_spindle_true.FirstOrDefault(q =>
                        q.equipid == machineIds[i]
                        && q.name == toolLocation.SpindleNo
                        && q.status == (int)RowState.Valid);
                    if (splindleEntity != null)
                    {
                        splindleId = splindleEntity.id;
                    }
                    else
                    {
                        var splindle = new SigerProjectToolSpindleTrue
                        {
                            status = (int)RowState.Valid,
                            create_time = UnixTimeHelper.GetNow(),
                            update_time = UnixTimeHelper.GetNow(),
                            equipid = machineIds[i],
                            name = toolLocation.SpindleNo,
                            productid = _prductid
                        };
                        apiToolDbContext.siger_project_tool_spindle_true.Add(splindle);
                        apiToolDbContext.SaveChanges();
                        splindleId = splindle.id;
                    }

                    var cutterQuery = from tcl in apiToolDbContext.siger_project_tool_cutter_location_true
                                      join sp in apiToolDbContext.siger_project_tool_spindle_true on tcl.spindleid equals sp.id
                                      where tcl.status == (int)RowState.Valid && sp.status == (int)RowState.Valid
                                                                              && sp.equipid == machineIds[i] && toolLocation.ToolLocationName == tcl.name
                                                                              && tcl.spindleid == splindleId && tcl.is_processing_program == (int)ProcessProgram.NoConfig
                                                                              && (tcl.programno == toolLocation.ProgramNo || tcl.subprogramno == toolLocation.ProgramNo)
                                      select tcl;
                    var cutter = cutterQuery.FirstOrDefault();

                    var value = (toolLocation.ISToolType == "是") ? (int)ToolType.Blade : (int)ToolType.NOBlade;

                    if (cutter == null)
                    {

                        var entity = new SigerProjectToolCutterLocationTrue
                        {
                            status = (int)RowState.Valid,
                            create_time = UnixTimeHelper.GetNow(),
                            update_time = UnixTimeHelper.GetNow(),
                            auto_study = 1,
                            program_type = 1,
                            programno = toolLocation.ProgramNo,
                            subprogramno = "",
                            is_processing_program = (int)ProcessProgram.MainProgram,
                            spindleid = splindleId,
                            productid = 0,
                            toolid = _toolid,
                            name = toolLocation.ToolLocationName,
                            ratedlife = toolLocation.RateLife.ToInt(),
                            is_identical_collection = 0,
                            type = value,
                            coefficent=toolLocation.Coefficent
                        };
                        apiToolDbContext.siger_project_tool_cutter_location_true.Add(entity);
                        apiToolDbContext.SaveChanges();
                    }
                    else
                    {
                        cutter.is_identical_collection = 1;
                        cutter.productid = _prductid;
                        cutter.update_time = UnixTimeHelper.GetNow();
                        cutter.ratedlife = toolLocation.RateLife.ToInt();
                        cutter.toolid = _toolid;
                        cutter.type = value;
                        cutter.coefficent = toolLocation.Coefficent;
                        if (cutter.programno == toolLocation.ProgramNo)
                        {
                            cutter.is_processing_program = (int)ProcessProgram.MainProgram;
                        }
                        else
                        {
                            cutter.is_processing_program = (int)ProcessProgram.ChildProgram;
                        }
                        apiToolDbContext.siger_project_tool_cutter_location_true.Update(cutter);
                        apiToolDbContext.SaveChanges();
                    }
                    toolImportInfo.Add(new ToolImportInfo
                    {
                        MachineId = machineIds[i],
                        ProgramNo = toolLocation.ProgramNo,
                        RateLife = toolLocation.RateLife.ToInt(),
                        ToolLocationName = toolLocation.ToolLocationName,
                        SpindleNo = toolLocation.SpindleNo,
                        type = value
                    });
                }
            }
            catch
            {
                throw;
            }
            return new ToolImportResult(1, "1", toolImportInfo);
        }


        public ProductData GetProduct(int id, int projectId)
        {
            var products = apiToolDbContext.siger_project_product.Where(q =>
                 q.projectid == projectId && q.id == id && q.status == (int)RowState.Valid).FirstOrDefault();

            var query = from p in apiToolDbContext.siger_project_product
                        where p.id == id && p.projectid == projectId && p.status == (int)RowState.Valid
                        select new ProductData
                        {
                            id = p.id,
                            name = p.name,
                            drawingcode = p.drawingcode
                        };
            return query.Where(f => true).FirstOrDefault();
        }

        public List<ResponseToolAlertSpindle> GetCutterLocationList(int sectionID, int companyId, int projectId, int page, int pagesize, out int totalCount)
        {
            var mids = GetMachineIds(sectionID, projectId);
            var result = from clt in apiToolDbContext.siger_project_tool_cutter_location
                         join st in apiToolDbContext.siger_project_tool_spindle on clt.spindleid equals st.id into tmp1
                         from t1 in tmp1.DefaultIfEmpty()
                         join m in apiToolDbContext.siger_project_machine on t1.equipid equals m.id
                         into tmp2
                         from t2 in tmp2.DefaultIfEmpty()
                         join i in
                         (
                              apiToolDbContext.siger_project_tool_alert_condition.Where(f => f.status == (int)RowState.Valid)
                              .GroupBy(f => f.cutterlocationid).Select(f => new
                              {
                                  f.FirstOrDefault().cutterlocationid,
                                  f.FirstOrDefault().status
                              })
                         ) on t2.id equals i.cutterlocationid
                         where t2.status == (int)RowState.Valid && clt.status == (int)RowState.Valid &&
                         t1.status == (int)RowState.Valid && t2.projectid == projectId &&
                         (mids.Count() == 0) ? true : mids.Contains(t2.id)
                         orderby t2.id, clt.id
                         select new ResponseToolAlertSpindle
                         {
                             id = clt.id,
                             mcode = t2.code,
                             mname = t2.title,
                             spindleid = t1.name,
                             cutterlocationid = clt.name,
                             isconfig = i.status
                         };

            totalCount = result.Count();
            result = result.Skip((page - 1) * pagesize).Take(pagesize);
            if (result.Count() == 0)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            return result.ToList();
        }

        public async Task<IEnumerable<CutterInfo>> GetCutterByProgramAsync(List<CNCEquipmentState> states)
        {
            return await Task.Run(() =>
            {
                var query = from cnc in states
                            join s in apiToolDbContext.siger_project_tool_spindle_true on cnc.MachineId equals s.equipid
                            join c in apiToolDbContext.siger_project_tool_cutter_location_true on s.id equals c.spindleid
                            where cnc.PN == c.programno && cnc.SPN == c.subprogramno && c.status == (int)RowState.Valid
                            select new CutterInfo
                            {
                                SpindleId = s.id,
                                SpinedleName = s.name,
                                Id = c.id,
                                Name = c.name,
                                Ratedlife = c.ratedlife,
                                ToolId = c.toolid,
                                IsProcess = c.is_processing_program,
                                Pn = c.programno,
                                Spn = c.subprogramno
                            };
                return query;
            });

        }

        /// <summary>
        /// 获取主轴-刀位
        /// </summary>
        /// <param name="machineid">设备ID</param>
        /// <returns></returns>
        public IEnumerable<ResponseCutterConfig> GetCutterConfigsByMachine(int machineid)
        {
            var query = from lsm in apiToolDbContext.siger_project_level_section_machine
                        join sp in apiToolDbContext.siger_project_tool_spindle_true on lsm.machine_id equals sp.equipid
                        join clt in apiToolDbContext.siger_project_tool_cutter_location_true on sp.id equals clt.spindleid
                        where lsm.machine_id == machineid && lsm.status == (int)RowState.Valid && sp.status == (int)RowState.Valid && clt.status == (int)RowState.Valid
                        select new ResponseCutterConfig
                        {
                            MachineId = lsm.machine_id,
                            SpindleName = sp.name,
                            CutterName = clt.name,
                            ToolId = clt.toolid == null ? 0 : clt.toolid
                        };
            return query.Distinct();
        }

        public List<MachineData> GetMachineBySection(List<int> section, int projectId)
        {
            var result = from lsm in apiToolDbContext.siger_project_level_section_machine
                         join m in apiToolDbContext.siger_project_machine on lsm.machine_id equals m.id
                         where lsm.status == (int)RowState.Valid && m.status == (int)RowState.Valid
                                                                  && m.projectid == projectId && section.Contains(lsm.section_id)
                         select new MachineData
                         {
                             section_id = lsm.section_id,
                             machine_id = m.id,
                             machine_code = m.code,
                             machine_name = m.title
                         };
            return result.ToList();
        }
    }
}


