using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Response;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository.Data.Acc;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Paged;

namespace Siger.Middlelayer.AccRepository.Repositories
{
    internal class BasketPositionRepository: AccRepositoryBase<siger_tr_basketful_position>, IBasketPositionRepository
    {
        private ApiAccDbContext accDbContext;
        public BasketPositionRepository(ApiAccDbContext context) : base(context)
        {
            accDbContext = context;
        }

        public IEnumerable<WrokCodeReport> GetReportsInfo(int projectId, int station = 0, string workCode = "")
        {
            Expression<Func<WrokCodeReport, bool>> FunStation = f => true;
            Expression<Func<WrokCodeReport, bool>> FunWorkCode = f => true;
            var querylist = from p in accDbContext.siger_tr_basketful_position
                            join st in accDbContext.siger_project_level_section on p.station equals st.id
                            join ps in accDbContext.siger_project_level_section on p.position equals ps.id
                            join pl in accDbContext.siger_project_machine_attribution on ps.id equals pl.station
                            join m in accDbContext.siger_project_machine on pl.machine equals m.id
                            where p.projectId == projectId && p.type==(int)Type_Status.basket && p.status != (int)BasketPosition_Status.Deleted
                            select new WrokCodeReport
                            {
                                id = p.id,
                                Station = p.station,
                                StationDesc = st.title,
                                Position = p.position,
                                PositionDesc = ps.title,
                                MachineId=m.id,
                                MachineCode=m.code,
                                MachineName=m.title,
                                OrderNum = p.orderno,
                                OrderCount = p.orderqty,
                                ProductBh = p.productbh,
                                ProductName = p.productname,
                                ProductType = p.producttype,
                                WorkCode = p.workcode,
                                Basket = p.basket,
                                Upload = p.upload,
                                Report = p.report,
                                Ng = p.nok, 
                                Ng2 = p.nok2
                                
                            };

            if (station != 0)
                FunStation = q => q.Station == station;
            if (!string.IsNullOrEmpty(workCode))
                FunWorkCode = q => q.WorkCode==workCode;

            var predicate = FunStation.And(FunWorkCode);

            return querylist.Where(predicate).OrderByDescending(o => o.id).ToList();
       ;
        }

        public IEnumerable<WrokCodeReport> GetReportsInfoDtl(int projectId, int station = 0, string workCode = "")
        {
            Expression<Func<WrokCodeReport, bool>> FunStation = f => true;
            Expression<Func<WrokCodeReport, bool>> FunWorkCode = f => true;
            var querylist = from p in accDbContext.siger_tr_basketful_position
                            join r in accDbContext.siger_tr_product_report on p.traceid equals r.TraceId
                            join st in accDbContext.siger_project_level_section on r.Station equals st.id
                            join ps in accDbContext.siger_project_level_section on r.Machine equals ps.id
                            join pl in accDbContext.siger_project_machine_attribution on ps.id equals pl.station
                            join m in accDbContext.siger_project_machine on pl.machine equals m.id
                            join u in accDbContext.siger_project_user on r.Uid equals u.mid into temp
                            from user in temp.DefaultIfEmpty()
                            where p.projectId == projectId && p.type == (int)Type_Status.basket && p.status != (int)BasketPosition_Status.Deleted
                            select new WrokCodeReport
                            {
                                id = p.id,
                                Station = p.station,
                                StationDesc = st.title,
                                Position = p.position,
                                PositionDesc = ps.title,
                                MachineId = m.id,
                                MachineCode = m.code,
                                MachineName = m.title,
                                OrderNum = p.orderno,
                                OrderCount = p.orderqty,
                                ProductBh = p.productbh,
                                ProductName = p.productname,
                                ProductType = p.producttype,
                                WorkCode = p.workcode,
                                Basket = p.basket,
                                Upload = p.upload,
                                Report = r.OkCount,
                                Ng = r.NokCount,
                                Ng2 = r.NokCount2,
                                Type=r.Type,
                                Status=r.ReportStatus,
                                User=user==null?r.Uid.ToString():user.name,
                                ReportTime=r.Time
                            };

            if (station != 0)
                FunStation = q => q.Station == station;
            if (!string.IsNullOrEmpty(workCode))
                FunWorkCode = q => q.WorkCode == workCode;

            var predicate = FunStation.And(FunWorkCode);

            return querylist.Where(predicate).OrderByDescending(o => o.id).ToList();
            
        }

        public IEnumerable<MachineStateWorkDtl> GetMachineReportsInfoDtlBydate(int projectId, DateTime begin, DateTime end)
        {
            var querylist = from p in accDbContext.siger_tr_basketful_position
                            join r in accDbContext.siger_tr_product_report on p.traceid equals r.TraceId
                            join st in accDbContext.siger_project_level_section on r.Station equals st.id
                            join ps in accDbContext.siger_project_level_section on r.Machine equals ps.id
                            join pl in accDbContext.siger_project_machine_attribution on ps.id equals pl.station
                            join m in accDbContext.siger_project_machine on pl.machine equals m.id
                            join u in accDbContext.siger_project_user on r.Uid equals u.mid into temp
                            from user in temp.DefaultIfEmpty()
                            where p.projectId == projectId && r.Time >= begin && r.Time <= end && p.type == (int)Type_Status.basket && p.status != (int)BasketPosition_Status.Deleted
                            select new MachineStateWorkDtl
                            {
                                MachineId=m.id,
                                MachineCode = m.code,
                                WorkCode = r.WorkCode,
                                PlanCount = p.orderqty,
                                CurrCount = r.OkCount,
                                TotalCount = p.report,
                                ProductId=p.productbh,
                                ProductName=p.productname,
                                ProductType=p.producttype
                                
                            };


            return querylist.OrderByDescending(o => o.MachineCode).ToList();
        }

        public IEnumerable<WrokCodeReport> GetReportsInfoDtlBydate(int projectId, DateTime begin, DateTime end ,List<int>position)
        {
            var querylist = from p in accDbContext.siger_project_product_plan
                            join r in accDbContext.siger_tr_product_report on p.code equals r.WorkCode
                            join st in accDbContext.siger_project_level_section on r.Station equals st.id
                            join ps in accDbContext.siger_project_level_section on r.Machine equals ps.id
                            join pl in accDbContext.siger_project_machine_attribution on ps.id equals pl.station
                            join m in accDbContext.siger_project_machine on pl.machine equals m.id
                            join u in accDbContext.siger_project_user on r.Uid equals u.mid into temp
                            from user in temp.DefaultIfEmpty()
                            where p.projectId == projectId && position.Contains(r.Machine) && 
                            r.Type == (int)Type_Status.basket && r.status == (int)Basket_Status.report &&
                            r.Time>=begin && r.Time<=end
                            select new WrokCodeReport
                            {
                                id = p.id,
                                Station = r.Station,
                                StationDesc = st.title,
                                Position = r.Machine,
                                PositionDesc = ps.title,
                                MachineId = m.id,
                                MachineCode = m.code,
                                MachineName = m.title,
                                OrderNum = p.ordernumber,
                                OrderCount = p.quantity,
                                ProductBh = p.product_code,
                                ProductName = p.product_name,
                                ProductType = p.draw_number,
                                WorkCode = p.code,
                                Basket = r.Number,
                              
                                Report = r.OkCount,
                                Ng = r.NokCount,
                                Ng2 = r.NokCount2,
                                Type = r.Type,
                                Status = r.ReportStatus,
                                User = user == null ? r.Uid.ToString() : user.name,
                                ReportTime = r.Time
                            };



            return querylist.OrderByDescending(o => o.id).ToList();
        }

        public IPagedCollectionResult<BasketPositionInfo> GetBasketPositionInfoList(string code, int projectId,int page, int pagesize)
        {
            Expression<Func<BasketPositionInfo, bool>> FunCode = f => true;
            var querylist = from p in accDbContext.siger_tr_basketful_position
                            join st in accDbContext.siger_project_level_section on p.station equals st.id
                            join ps in accDbContext.siger_project_level_section on p.position equals ps.id
                            join pl in accDbContext.siger_project_machine_attribution on ps.id equals pl.station
                            join m in accDbContext.siger_project_machine on pl.machine equals m.id
                            where p.projectId==projectId && p.status==(int)BasketPosition_Status.validate
                            select new BasketPositionInfo
                            {
                                 Station=st.title,
                                 Position=ps.title,
                                 MachineCode=m.code,
                                 OrderCode=p.orderno,
                                 WorkCode=p.workcode,
                                 BasketNumber=p.basket==null?"":p.basket,
                                 PrdNumber=p.productbh,
                                 PrdtName=p.productname,
                                 ModelType=p.producttype,
                                 UploadCount=p.upload,
                                 ReportCount=p.report,
                                 NgCount=p.nok,
                                 NgCount2=p.nok2,
                                // Count=p.report,
                                 UploadTime=p.uploadtime,
                                 PositionType=p.type,
                                 CurrBasket=p.currbasket
                            };
            if (!string.IsNullOrEmpty(code))
            {
                FunCode = q => q.MachineCode.Contains(code);
            }
            var entities = querylist.Where(FunCode).OrderByDescending(q => q.MachineCode).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
            var totalCount = querylist.Where(FunCode).Count();
            return new PagedCollectionResult<BasketPositionInfo>(entities, totalCount);
        }

        /// <summary>
        /// 工站 料框报工记录
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="begin"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public IEnumerable<ReportInfoDetail> GetReportStationDtl(int projectId, DateTime begin, DateTime end)
        {
            var querylist = from p in accDbContext.siger_tr_basketful_position
                            join r in accDbContext.siger_tr_product_report on p.traceid equals r.TraceId
                            join st in accDbContext.siger_project_level_section on r.Station equals st.id
                            join ps in accDbContext.siger_project_level_section on r.Machine equals ps.id
                            where p.projectId == projectId && p.status!=(int)BasketPosition_Status.Deleted && r.Type== (int)Type_Status.basket && r.ReportStatus == (int)Basket_Status.report &&
                            r.Time >= begin && r.Time <= end
                            select new ReportInfoDetail
                            {
                                WorkCode = p.workcode,
                                OrderNo = p.orderno,
                                OrderCount = p.orderqty,
                                Type = r.Type,
                                Report = r.ReportStatus,
                                Station = st.title,
                                Position = ps.title,
                                OkCount = r.OkCount,
                                NgCount = r.NokCount,
                                NgCount2 = r.NokCount2

                            };
            return querylist.AsEnumerable();
        }

        public IEnumerable<BasketTotal> GetReportTotalByDate(int projectId, string productBh, string productName, string productType, string orderNo, string wo, int section, DateTime begin, DateTime end)
        {
            var positions = GetSonLevelSectionIds(section, projectId);
            Expression<Func<BasketTotal, bool>> FunPd = f => true;
            Expression<Func<BasketTotal, bool>> FunOrder = f => true;
            Expression<Func<BasketTotal, bool>> FunWo = f => true;
            var query = from p in accDbContext.siger_tr_basket_report_ttl
                        join s in accDbContext.siger_project_level_section on p.Station equals s.id
                        join ps in accDbContext.siger_project_level_section on p.Position equals ps.id
                        where p.projectId == s.projectid && p.projectId == projectId &&
                        positions.Contains(p.Position) &&
                        p.BusiDate >= begin && p.BusiDate <= end &&
                        p.status == (int)BasketPosition_Status.validate
                        select new BasketTotal
                        {
                            ProductBh = p.ProductBh,
                            ProductName = p.ProductName,
                            ProductType = p.ProductType,
                            Station = s.title,
                            Postion = ps.title,
                            OrderNo = p.OrderNo,
                            Wo = p.WO,
                            OrderQty = p.OrderQty,
                            OkCount = p.OkCount,
                            NgCount = p.NgCount,
                            NgCount2 = p.NgCount2
                        };
            if (!string.IsNullOrEmpty(productBh))
                FunPd = q => q.ProductBh.Contains(productBh);
            if (!string.IsNullOrEmpty(productName))
                FunPd = q => q.ProductName.Contains(productName);
            if (!string.IsNullOrEmpty(productType))
                FunPd = q => q.ProductType.Contains(productType);
            if (!string.IsNullOrEmpty(orderNo))
                FunOrder = q => q.OrderNo.Contains(orderNo);
            if (!string.IsNullOrEmpty(wo))
                FunWo = q => q.Wo == wo;
            var predicate = FunPd.And(FunOrder).And(FunWo);
            //  return query.Where(predicate).OrderByDescending(o => o.Wo).ToList();

            //3:选 工单 :按产品-订单汇-工单 汇总
            if (!string.IsNullOrEmpty(wo))
            {
                return query.Where(predicate).OrderBy(o => o.ProductBh).ThenBy(o=>o.OrderNo).ThenBy(o=>o.Wo).ThenBy(o=>o.Station).ThenBy(o=>o.Postion)
                  .GroupBy(x => new { x.ProductBh, x.ProductName, x.ProductType, x.Station, x.Postion, x.OrderNo, x.Wo })
                  .Select(g => new BasketTotal
                  {
                      ProductBh = g.Key.ProductBh,
                      ProductName = g.Key.ProductName,
                      ProductType = g.Key.ProductType,
                      Station = g.Key.Station,
                      Postion = g.Key.Postion,
                      OrderNo = g.Key.OrderNo,
                      OrderQty = g.FirstOrDefault() == null ? 0 : g.FirstOrDefault().OrderQty,
                      Wo = g.Key.Wo,
                      OkCount = g.Sum(s => s.OkCount),
                      NgCount = g.Sum(s => s.NgCount),
                      NgCount2 = g.Sum(s => s.NgCount2),
                      NgRate = Math.Round((g.Sum(s => s.NgCount) + g.Sum(s => s.NgCount2)) / Convert.ToDouble(g.Sum(s => s.OkCount) + g.Sum(s => s.NgCount) + g.Sum(s => s.NgCount2)), 2)
                  }).ToList();
            }
            //2 选 订单 :按产品- 订单
            if (!string.IsNullOrEmpty(orderNo))
            {
                return query.Where(predicate).OrderBy(o => o.ProductBh).ThenBy(o => o.OrderNo).ThenBy(o => o.Wo).ThenBy(o => o.Station).ThenBy(o => o.Postion)
                    .GroupBy(x => new { x.ProductBh, x.ProductName, x.ProductType, x.Station, x.Postion, x.OrderNo })
                    .Select(g => new BasketTotal
                    {
                        ProductBh = g.Key.ProductBh,
                        ProductName = g.Key.ProductName,
                        ProductType = g.Key.ProductType,
                        Station = g.Key.Station,
                        Postion = g.Key.Postion,
                        OrderNo = g.Key.OrderNo,
                        OkCount = g.Sum(s => s.OkCount),
                        NgCount = g.Sum(s => s.NgCount),
                        NgCount2 = g.Sum(s => s.NgCount2),
                        NgRate = Math.Round((g.Sum(s => s.NgCount) + g.Sum(s => s.NgCount2)) / Convert.ToDouble(g.Sum(s => s.OkCount) + g.Sum(s => s.NgCount) + g.Sum(s => s.NgCount2)), 2)
                    }).ToList();
            }
            //1/0  产品  //都不选 ( 按产品汇总)

            return query.Where(predicate).OrderBy(o => o.ProductBh).ThenBy(o => o.OrderNo).ThenBy(o => o.Wo).ThenBy(o => o.Station).ThenBy(o => o.Postion)
              .GroupBy(x => new { x.ProductBh, x.ProductName, x.ProductType, x.Station, x.Postion, })
              .Select(g => new BasketTotal
              {
                  ProductBh = g.Key.ProductBh,
                  ProductName = g.Key.ProductName,
                  ProductType = g.Key.ProductType,
                  Station = g.Key.Station,
                  Postion = g.Key.Postion,
                  OkCount = g.Sum(s => s.OkCount),
                  NgCount = g.Sum(s => s.NgCount),
                  NgCount2 = g.Sum(s => s.NgCount2),
                  NgRate = Math.Round((g.Sum(s => s.NgCount) + g.Sum(s => s.NgCount2)) / Convert.ToDouble(g.Sum(s => s.OkCount) + g.Sum(s => s.NgCount) + g.Sum(s => s.NgCount2)), 2)
              }).ToList();


        }
    }
}
