using Microsoft.EntityFrameworkCore;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Request;
using Siger.Middlelayer.AccRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Paged;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Text;

namespace Siger.Middlelayer.AccRepository.Repositories
{
    internal class SigetTrAssemblyDetails : AccRepositoryBase<siger_tr_assemb_details>, ISigetTrAssemblyDetails
    {
        private ApiAccDbContext accDbContext;
        public SigetTrAssemblyDetails(ApiAccDbContext context) : base(context)
        {
            accDbContext = context;
        }
        public IEnumerable<ResponseProduct> GetDataBySn(string SN, int projectId)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<ResponseMateNumber> GetNumber(string SN, int projectId)
        {
            var mateList = from q in accDbContext.siger_tr_assist_materials
                           where q.batch == SN && q.projectId == projectId && q.status == (int)RowState.Valid
                           select new ResponseMateNumber
                           {
                               number = q.number,
                           };

            return mateList.ToList();
        }

        IPagedCollectionResult<RequestAssembleBySnList> ISigetTrAssemblyDetails.GetAssembleBySn(RequestAssembleBySn condition, int pid)
        {
            var InPart = accDbContext.siger_tr_assemb_details.Where(a => a.projectId == pid && a.status == (int)RowState.Valid && a.ispart == (int)ProductType.InPart);
            var Part = accDbContext.siger_tr_assemb_details.Where(a => a.projectId == pid && a.status == (int)RowState.Valid && a.ispart == (int)ProductType.Part);
            var snData = from s in InPart
                         join q in accDbContext.siger_tr_sn_list on s.sn equals q.SN
                         join r in accDbContext.siger_project_product on q.ProductId equals r.id
                         join d in accDbContext.siger_tr_sn_trace on s.guid equals d.SeqID
                         join s1 in Part on s.guid equals s1.guid into sd
                         from ss in sd.DefaultIfEmpty()
                         where s.projectId == pid && s.status == (int)RowState.Valid && 
                              q.projectId == pid && q.status == (int)RowState.Valid  &&
                              s.ispart == (int)ProductType.InPart && 
                              ss.ispart == (int)ProductType.Part &&
                              ss.projectId == pid && ss.status == (int)RowState.Valid
                         select new RequestAssembleBySnList()
                         {
                             guid=s.guid,
                             Sn = s.sn,
                             ProductID = q.ProductCode,
                             Line = ss.section.ToStr(),
                             WO = q.WO,
                             PN = q.PN == null ? "" : q.PN,
                             ResultStatus = d.Result,
                             InputDateTime = s.busidate,
                             TransDateTime = s.busidate,
                             parentSN = ss.sn,
                             status = s.status,
                             productname=r.name,
                             productdraw=r.drawingcode
                         };
            Expression<Func<RequestAssembleBySnList, bool>> FunSn = f => true;
            if (!string.IsNullOrEmpty(condition.Sn))
                FunSn = f => f.Sn.Contains(condition.Sn) || f.WO.Contains(condition.Sn);
            var totalCount = snData.Count(FunSn);
            var resultList = snData.Where(FunSn).OrderByDescending(o => o.id).Skip((condition.page - 1) * condition.pagesize)
                .Take(condition.pagesize).AsNoTracking();
            return new PagedCollectionResult<RequestAssembleBySnList>(resultList, totalCount);
        }

        IPagedCollectionResult<RequestAssembleBySnList> ISigetTrAssemblyDetails.GetAssembleData(RequestAssembleData condition, int pid)
        {


            Expression<Func<RequestAssembleBySnList, bool>> FunTime = f => true;
            Expression<Func<RequestAssembleBySnList, bool>> FunProduct = f => true;
            Expression<Func<RequestAssembleBySnList, bool>> FunPn = f => true;
            //station init
            var stations = GetSonLevelSectionIds(condition.Station, pid).ToList();
            stations.Add(condition.Station);
            Expression<Func<RequestAssembleBySnList, bool>> FunStation = f => stations.Contains(f.station);
            if ((!string.IsNullOrEmpty(condition.DtStart.ToStr())) &&
                (!string.IsNullOrEmpty(condition.DtEnd.ToStr())))
            if (!string.IsNullOrEmpty(condition.ProductId))
                FunProduct = f => f.ProductID.Equals(condition.ProductId);
            if (!string.IsNullOrEmpty(condition.Pn))
                FunPn = f => f.PN == condition.Pn;
            
            FunTime = f => f.TransDateTime >= condition.DtStart && f.TransDateTime <= condition.DtEnd.AddDays(1).AddSeconds(-1);
            var predicate = FunTime.And(FunProduct).And(FunPn).And(FunStation);
            var InPart = accDbContext.siger_tr_assemb_details.Where(a => a.projectId == pid && a.status == (int)RowState.Valid && a.ispart == (int)ProductType.InPart);
            var Part = accDbContext.siger_tr_assemb_details.Where(a => a.projectId == pid && a.status == (int)RowState.Valid && a.ispart == (int)ProductType.Part);
            var snData = from s in InPart
                         join q in accDbContext.siger_tr_sn_list on s.sn equals q.SN
                         join r in accDbContext.siger_project_product on q.ProductId equals r.id
                         join d in accDbContext.siger_tr_sn_trace on s.guid equals d.SeqID
                         join s1 in Part on s.guid equals s1.guid into sd
                         from ss in sd.DefaultIfEmpty()
                         where s.projectId == pid && s.status == (int)RowState.Valid &&
                              q.projectId == pid && q.status == (int)RowState.Valid &&
                              s.ispart == (int)ProductType.InPart &&
                              ss.ispart == (int)ProductType.Part &&
                              ss.projectId == pid && ss.status == (int)RowState.Valid
                         select new RequestAssembleBySnList()
                         {
                             guid = s.guid,
                             Sn = s.sn,
                             ProductID = q.ProductCode,
                             Line = ss.section.ToStr(),
                             WO = q.WO,
                             PN = q.PN == null ? "" : q.PN,
                             ResultStatus = d.Result,
                             InputDateTime = s.busidate,
                             TransDateTime = s.busidate,
                             parentSN = ss.sn,
                             status = s.status,
                             productdraw = r.drawingcode,
                             productname = r.name,
                             station=d.Station
                         };
            var totalCount = snData.Count(predicate);
            var resultList = snData.Where(predicate).OrderByDescending(o => o.TransDateTime)
                .Skip((condition.page - 1) * condition.pagesize).Take(condition.pagesize).AsNoTracking();
            return new PagedCollectionResult<RequestAssembleBySnList>(resultList, totalCount);
        }
    }
}
