using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.FieldEnum;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Paged;
using Siger.Middlelayer.TlmRepository.Entities;
using Siger.Middlelayer.TlmRepository.Repositories.Interface;
using Siger.Middlelayer.TlmRepository.Request;
using Siger.Middlelayer.TlmRepository.Response;
using Siger.Middlelayer.WmsRepository.Request;

namespace Siger.Middlelayer.TlmRepository.Repositories
{
    internal class ToolLifeToolInstallRepository : TlmRepositoryBase<siger_project_toollife_tool_install>, IToolLifeToolInstallRepository
    {
        private readonly ApiTlmDbContext _context;
        public ToolLifeToolInstallRepository(ApiTlmDbContext context) : base(context)
        {
            _context = context;
        }

        public IPagedCollectionResult<ResponseGetInstallList> GetPagedList(IEnumerable<string> machineCodes, string cutter_number, int page, int pagesize, int projectId, int toexcel, string loadTime = "")
        {
            var querylist = from q in _context.siger_project_toollife_tool_install
                            join u in _context.siger_project_user on q.install_userid equals u.mid
                            where q.status != (int)RowState.Invalid && q.project_id == projectId && q.install_category == InstallCategory.Install
                            select new ResponseGetInstallList
                            {
                                id = q.id,
                                machine_code = q.machine_code,
                                cutter_number = q.cutter_number,
                                install_time = q.create_time.ToString(ParameterConstant.DateTimeFormat),
                                install_user = u.name ?? "",
                                serial_number = q.tool_code,
                                tool_life = q.lastLife,
                                tool_type = q.tool_category,
                            };
            Expression<Func<ResponseGetInstallList, bool>> machineCodeExpression = q => true;
            if (machineCodes.Any())
            {
                machineCodeExpression = q => machineCodes.Contains(q.machine_code);
            }
            Expression<Func<ResponseGetInstallList, bool>> cutterNumberExpression = q => true;
            if (!string.IsNullOrWhiteSpace(cutter_number))
            {
                cutterNumberExpression = q => q.cutter_number == cutter_number;
            }
            Expression<Func<ResponseGetInstallList, bool>> loadTimeExpression = q => true;
            if (!string.IsNullOrWhiteSpace(loadTime))
            {
                loadTimeExpression = q => q.install_time == loadTime;
            }
            var expression = machineCodeExpression.And(cutterNumberExpression).And(loadTimeExpression);

            if (toexcel == 0)
            {
                var dataList = querylist.Where(expression).ToList();
                var groupCode = querylist.Select(t => t.machine_code).Distinct().ToList();
                var res = new List<ResponseGetInstallList>();
                foreach (var code in groupCode)
                {
                    res.AddRange(dataList.Where(t => t.machine_code == code).GroupBy(t => t.cutter_number).Select(t => t.FirstOrDefault()));
                }
                var totalCount = res.Count();
                List<ResponseGetInstallList> entities;
                if (pagesize != 0)
                {
                    entities = res.Skip((page - 1) * pagesize).Take(pagesize).ToList();
                }
                else
                {
                    entities = res.ToList();
                }

                var stockList = _context.siger_wms_stock.Where(f => f.projectid == projectId && f.status != 0).AsNoTracking().ToList();
                foreach (var item in entities)
                {
                    var materialId = stockList.FirstOrDefault(f => f.serial_number == item.serial_number || f.batch_number == item.serial_number)?.material_id ?? 0;
                    var material = _context.siger_project_toollife_tool.FirstOrDefault(f => f.material_id == materialId);
                    item.tool_number = material?.number ?? "";
                    item.tool_name = material?.name ?? "";
                }
                return new PagedCollectionResult<ResponseGetInstallList>(entities, totalCount);
            }
            else
            {
                var entities = querylist.Where(expression).AsNoTracking().ToList();
                return new PagedCollectionResult<ResponseGetInstallList>(entities, 0);
            }
        }

        public IPagedCollectionResult<ResponseToolInstallInfo> GetToolInstallInfo(RequestToolInstallInfo req, int projectId)
        {
            var ret = new List<ResponseToolInstallInfo>();
            var query = _context.siger_project_toollife_tool_install.Where(f => f.project_id == projectId && f.status != 0 
            //&& f.install_category == InstallCategory.UnInstall
            //&& f.tool_category == 2
            );
            Expression<Func<ResponseToolInstallInfo, bool>> funToolNumber = f => true;
            if (!string.IsNullOrEmpty(req.toolNumber))
            {
                funToolNumber = f => f.toolCode == req.toolNumber;
            }
            Expression<Func<ResponseToolInstallInfo, bool>> funBusinessId = f => true;
            if (req.businessId != 0)
            {
                funBusinessId = f => f.businessId == req.businessId;
            }
            Expression<Func<ResponseToolInstallInfo, bool>> funTime = f => true;
            if (req.start > 0 && req.end > 0)
            {
                var start = UnixTimeHelper.ConvertStringDateTime(req.start.ToStr());
                var end = UnixTimeHelper.ConvertStringDateTime(req.end.ToStr());
                funTime = f => f.createtime >= start && f.createtime <= end;
            }
            Expression<Func<ResponseToolInstallInfo, bool>> funInstallUser = f => true;
            if (req.installUser.ToInt() != 0)
            {
                funInstallUser = f => f.installUserId == req.installUser.ToInt();
            }
            Expression<Func<ResponseToolInstallInfo, bool>> funMachine = f => true;
            if (!string.IsNullOrEmpty(req.machineCode))
            {
                funMachine = f => f.machineCode == req.machineCode;
            }
            Expression<Func<ResponseToolInstallInfo, bool>> funToolLocaltion = f => true;
            if (!string.IsNullOrEmpty(req.toolLocaltion))
            {
                funToolLocaltion = f => f.toolLocaltion == req.toolLocaltion;
            }
            Expression<Func<ResponseToolInstallInfo, bool>> funSection = f => true;
            if (req.section != 0)
            {
                var codes = GetMachineInfo(req.section, projectId).Select(s => s.code);
                funSection = f => codes.Contains(f.machineCode);
            }
            Expression<Func<ResponseToolInstallInfo, bool>> funCommon = f => f.category == TlmSettingCategory.Cutter;
            var predicate = funToolNumber.And(funBusinessId).And(funTime).And(funInstallUser).And(funMachine).And(funToolLocaltion).And(funSection).And(funCommon);

            var queryTool = _context.siger_project_toollife_tool.Where(f => f.status != 0 && f.project_id == projectId);

            var actualQuery = from q in query
                                  //join m in _context.siger_tr_materials on q.material_id equals m.id into t2
                                  //from m in t2.DefaultIfEmpty()
                              join u in _context.siger_project_user on q.install_userid equals u.mid into t3
                              from u in t3.DefaultIfEmpty()
                              join ma in _context.siger_project_machine on q.machine_code equals ma.code into t4
                              from ma in t4.DefaultIfEmpty()
                              join stock in _context.siger_wms_stock_detail on q.tool_code equals stock.serialNumber into t5
                              from stock in t5.DefaultIfEmpty()
                              join t in queryTool on stock.inventory equals t.material_id into t1
                              from t in t1.DefaultIfEmpty()
                              orderby q.id descending
                              select new ResponseToolInstallInfo
                              {
                                  createtime = q.create_time,
                                  installTime = q.create_time.ToString(UnixTimeHelper.DateTimeFormat),
                                  id = q.id,
                                  installUserId = q.install_userid,
                                  life = q.lastLife ?? "",
                                  machineCode = q.machine_code,
                                  toolLocaltion = q.cutter_number,
                                  uninstallReason = q.uninstall_reason ?? "",
                                  uninstallTime = q.uninstall_time == default ? "" : q.uninstall_time.ToString(UnixTimeHelper.DateTimeFormat),
                                  serialNumber = q.tool_code,
                                  materialId = q.material_id,
                                  supplier = stock.businessName,
                                  toolCode = t.number,
                                  toolName = t.name,
                                  installUser = u.name,
                                  machineName = ma.title,
                                  businessId = stock.businessid,
                                  category = t.category
                              };
            actualQuery = actualQuery.GroupBy(g => g.id).Select(s => s.FirstOrDefault());
            var total = actualQuery.Count(predicate);
            if (req.toExcel.ToInt() == 0)
            {
                ret = actualQuery.Where(predicate).OrderByDescending(o => o.createtime).Skip((req.page - 1) * req.pagesize).Take(req.pagesize).AsNoTracking().ToList();
            }
            else
            {
                ret = actualQuery.Where(predicate).OrderByDescending(o => o.createtime).AsNoTracking().ToList();
            }
            return new PagedCollectionResult<ResponseToolInstallInfo>(ret, total);
        }
        public IEnumerable<ResponseGetInstallStock> GetSupplierUnusualList(string reason, string starttime, string endtime, int projectId)
        {
            var installList = _context.siger_project_toollife_tool_install.Where(t => t.status == (int)RowState.Valid && t.project_id == projectId &&
                t.install_category == InstallCategory.UnInstall);

            var query = from q in installList
                        join m in _context.siger_wms_stock on q.tool_code equals string.IsNullOrEmpty(m.serial_number) ? m.batch_number : m.serial_number
                        join b in _context.siger_wms_bussinese_contacts on m.businessid equals b.id
                        where b.supply_type == (int)WMSEnum.Business
                        select new ResponseGetInstallStock
                        {
                            pn = m.material_pn,
                            material_id = m.material_id,
                            stock_id = m.id,
                            bussiness_id = b.id,
                            bussiness_name = b.name,
                            reason = q.uninstall_reason,
                            unistall_time = q.uninstall_time
                        };

            Expression<Func<ResponseGetInstallStock, bool>> reasonExpression = f => true;
            Expression<Func<ResponseGetInstallStock, bool>> timeExpression = f => true;
            if (!string.IsNullOrEmpty(reason))
            {
                reasonExpression = f => f.reason == reason;
            }
            if (!string.IsNullOrEmpty(starttime) && !string.IsNullOrEmpty(endtime))
            {
                timeExpression = f => f.unistall_time <= endtime.ToDateTime() && f.unistall_time >= starttime.ToDateTime();
            }

            var expression = reasonExpression.And(timeExpression);
            var unusualList = query.Where(expression).ToList();

            return unusualList;
        }
        /// <summary>
        /// 获取刀具使用信息
        /// </summary>
        /// <param name="code">道具号</param>
        /// <param name="startTime">安装开始时间</param>
        /// <param name="endTime">安装结束时间</param>
        /// <param name="uid">安装人</param>
        /// <param name="pid"></param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <param name="materialcode">料号</param>
        /// <param name="supplier">供应商</param>
        /// <param name="toolname">刀具名</param>
        /// <returns></returns>
        public IPagedCollectionResult<ResponseToolUseData> GetToolUseData(string code, DateTime startTime, DateTime endTime, int uid, int pid, int page, int pageSize,
            string materialcode = null, string supplier = null, string toolname = null)
        {
            var query = from tti in _context.siger_project_toollife_tool_install
                        join user in _context.siger_project_user on tti.install_userid equals user.mid
                        join stock1 in _context.siger_wms_stock_detail on tti.tool_code equals stock1.batch into temp1
                        from stock1 in temp1.DefaultIfEmpty()
                        join stock2 in _context.siger_wms_stock_detail on tti.tool_code equals stock2.serialNumber into temp2
                        from stock2 in temp2.DefaultIfEmpty()
                        where tti.create_time >= startTime && tti.create_time <= endTime && tti.project_id.Equals(pid) && tti.status == (int)RowState.Valid
                        select new ResponseToolUseData
                        {
                            package_id = tti.package_id,
                            Id = tti.id,
                            InstallTime = tti.create_time,
                            UninstallTime = tti.uninstall_time,
                            Reason = tti.uninstall_reason,
                            SerialNo = tti.tool_code,
                            Installer = user.name,
                            uid = tti.install_userid,
                            Position = tti.cutter_number,
                            ProcessCount = tti.lastLife,
                            machine_code = tti.machine_code,
                            Supplier = stock1!=null?stock1.businessName: stock2 != null ? stock2.businessName:"",
                            Name = stock1 != null ? stock1.inventoryName : stock2 != null ? stock2.inventoryName : "",
                            MaterialCode = stock1 != null ? stock1.inventorySN : stock2 != null ? stock2.inventorySN : "",
                        };
            Expression<Func<ResponseToolUseData, bool>> funcCode = f => true;
            if (!string.IsNullOrEmpty(code))
            {
                funcCode = f => f.SerialNo.ToLower().Contains(code.ToLower());
            }
            Expression<Func<ResponseToolUseData, bool>> funcUid = f => true;
            if (uid != 0)
            {
                funcUid = f => f.uid == uid;
            }
            Expression<Func<ResponseToolUseData, bool>> funcMaterialCode = f => true;
            if (!string.IsNullOrEmpty(materialcode))
            {
                funcMaterialCode = f => !string.IsNullOrEmpty(f.MaterialCode)&&f.MaterialCode.Equals(materialcode, StringComparison.OrdinalIgnoreCase);
            }
            Expression<Func<ResponseToolUseData, bool>> funcSupplier = f => true;
            if (!string.IsNullOrEmpty(supplier))
            {
                var serialNumbers = _context.siger_wms_stock_detail.Where(f => f.businessName == supplier && f.projectid == pid && !string.IsNullOrEmpty(f.serialNumber)).Select(s => s.serialNumber).Distinct().ToList();
                var batchs = _context.siger_wms_stock_detail.Where(f => f.businessName == supplier && f.projectid == pid && !string.IsNullOrEmpty(f.batch)).Select(s => s.batch).Distinct().ToList();
                funcSupplier = f => serialNumbers.Contains(f.SerialNo) || batchs.Contains(f.SerialNo);
            }
            Expression<Func<ResponseToolUseData, bool>> funcToolname = f => true;
            if (!string.IsNullOrEmpty(toolname))
            {
                funcToolname = f => f.Name.ToLower().Contains(toolname.ToLower());
            }
            var predicate = funcCode.And(funcUid).And(funcMaterialCode).And(funcSupplier).And(funcToolname);
            var count = query.Count(predicate);
            var entities = query.Where(predicate).Skip((page - 1) * pageSize).Take(pageSize).ToList();
            foreach (var item in entities)
            {
                //var stock = _context.siger_wms_stock_detail.FirstOrDefault(f => (f.no == item.SerialNo || f.batch == item.SerialNo) && f.projectid == pid);
                //item.Supplier = stock?.businessName ?? "";
                //item.Name = stock?.inventoryName ?? "";
                //item.MaterialCode = stock?.inventorySN ?? "";
                item.Location = _context.siger_project_machine.FirstOrDefault(f => f.code == item.machine_code)?.title ?? "";
                item.mid = _context.siger_project_machine.FirstOrDefault(f => f.projectid == pid && f.status != 0 && f.code == item.machine_code)?.id ?? 0;
            }
            return new PagedCollectionResult<ResponseToolUseData>(entities, count);
        }

        public List<ToolLifeConfigData> GetToolLifeConfigData(int pid, int mid)
        {
            var ret = new List<ToolLifeConfigData>();
            var machineCode = _context.siger_project_machine.FirstOrDefault(f => f.projectid == pid && f.status != 0 && f.id == mid)?.code ?? "";
            var install = _context.siger_project_toollife_tool_install.Where(f => f.project_id == pid && f.status != 0 && f.machine_code == machineCode && f.install_category == InstallCategory.Install)
                .OrderByDescending(o => o.id);
            foreach (var item in install)
            {
                var boomList = _context.ProjectToollifeToolConfigEntities.Where(f => f.Code == item.boom_code && f.Projectid == pid && f.Status != 0).Select(s => s.ToolId);
                if (!boomList.Any())
                {
                    continue;
                }
                var toolList = _context.siger_project_toollife_tool.Where(f => f.project_id == pid && f.status != 0 && boomList.Contains(f.id) && f.category == TlmSettingCategory.Cutter).AsNoTracking().ToList();
                var model = new ToolLifeConfigData
                {
                    toolids = toolList.Select(s => s.id).ToList(),
                    Location = item.cutter_number,
                };
                ret.Add(model);
            }
            return ret;
        }
    }
}
