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.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Repository.Data;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Paged;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.Middlelayer.AccRepository.Repositories
{
    internal class SigerTrAssemblyMaintenanceRepository : AccRepositoryBase<SigerTrAssemblyMaintenance>, ISigerTrAssemblyMaintenanceRepository
    {
        private readonly ApiAccDbContext accDbContext;
        public SigerTrAssemblyMaintenanceRepository(ApiAccDbContext context) : base(context)
        {
            accDbContext = context;
        }

        public PagedCollectionResult<AssemblyMaintenance> GetPagedList(List<int> stationids, string serial_number, string parent_serial,
            string child_serial,int projectid, int page, int pagesize)
        {
            var query=from a in accDbContext.siger_tr_assembly_maintenance
                      join s in accDbContext.siger_project_level_section on a.station equals s.id
                      join ps in accDbContext.siger_project_level_section on s.parentid equals ps.id
                      join p in accDbContext.siger_project_product on a.serial_number equals p.code
                      //join m in accDbContext.siger_tr_materials on a.parent_serial_pn equals m.pn into mtemp
                      //from m in mtemp.DefaultIfEmpty()
                      //join sm in accDbContext.siger_tr_materials on a.child_serial_pn equals sm.pn into smtemp
                      //from sm in smtemp.DefaultIfEmpty()
                      where a.projectId==projectid && stationids.Contains(a.station) && a.status==(int)RowState.Valid
                      select new AssemblyMaintenance
                      {
                          //id = p.id,
                          id=a.id,
                          line = s.parentid,
                          station = s.id,
                          line_value = ps.title,
                          station_value = s.title,
                          serial_number = p.name,
                          serial_number_value = p.code,
                          parent_serial = a.parent_serial,
                          parent_serial_value = a.parent_serial_pn,
                          child_serial = a.child_serial,
                          child_serial_value =a.parent_serial_pn,
                          quantity = a.quantity,
                          role = a.role,
                          transdatetime = a.TransDateTime.ToString(ParameterConstant.DateTimeFormat)
                      };

            Expression<Func<AssemblyMaintenance, bool>> Funserialnumber = f => true;
            Expression<Func<AssemblyMaintenance, bool>> Funparentserial = f => true;
            Expression<Func<AssemblyMaintenance, bool>> Funchildserial = f => true;
           
            if (!string.IsNullOrEmpty(serial_number) && serial_number != "0")
                Funserialnumber = f => f.serial_number == serial_number;
            if (!string.IsNullOrEmpty(parent_serial) && parent_serial != "0")
                Funparentserial = f => (f.parent_serial_value == parent_serial || f.child_serial_value == parent_serial);
            if (!string.IsNullOrEmpty(child_serial) && child_serial != "0")
                Funchildserial = f => f.child_serial_value == child_serial;
          
            var predicate = Funserialnumber.And(Funparentserial).And(Funchildserial).And(Funchildserial);

            var totalCount = query.Count(predicate);
            var entities = query.Where(predicate).OrderByDescending(q => q.id).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
            return new PagedCollectionResult<AssemblyMaintenance>(entities, totalCount);


            //int rowstate = (int)RowState.Valid;
            //var AssemblyMaintenances =
            //    accDbContext.siger_tr_assembly_maintenance.Where(q => q.status == (int)RowState.Valid && q.projectId == projectid);
            //var query = from p in AssemblyMaintenances
            //            join m in accDbContext.siger_project_level_section
            //            on new { lineid = p.line, rowstatus = rowstate }
            //            equals new { lineid = m.id, rowstatus = m.status }
            //            into linetemp
            //            from m in linetemp.DefaultIfEmpty()
            //            join q in accDbContext.siger_project_level_section
            //            on new { stationid = p.station, rowstatus = rowstate }
            //            equals new { stationid = q.id, rowstatus = q.status }
            //            into stationtemp
            //            from q in stationtemp.DefaultIfEmpty()
            //            join pi in accDbContext.siger_project_product
            //            on new { productid = p.serial_number, projectids = projectid, rowstatus = rowstate }
            //            equals new { productid = pi.code, projectids = pi.projectid, rowstatus = pi.status }
            //            into producttemp
            //            from pi in producttemp.DefaultIfEmpty()
            //            join mp in accDbContext.siger_tr_materials
            //            on new { materialid = p.parent_serial_pn, projectids = projectid, rowstatus = rowstate }
            //            equals new { materialid = mp.pn, projectids = mp.projectId, rowstatus = mp.status }
            //            into mptemp
            //            from mp in mptemp.DefaultIfEmpty()
            //            join mc in accDbContext.siger_tr_materials
            //            on new { materialid = p.child_serial_pn, projectids = projectid, rowstatus = rowstate }
            //            equals new { materialid = mc.pn, projectids = mc.projectId, rowstatus = mc.status }
            //            into mctemp
            //            from mc in mctemp.DefaultIfEmpty()
            //            select new AssemblyMaintenance
            //            {
            //                id = p.id,
            //                line = p.line,
            //                station = p.station,
            //                line_value = m.title,
            //                station_value = q.title,
            //                serial_number = p.serial_number,
            //                serial_number_value = pi.code,
            //                parent_serial = p.parent_serial,
            //                parent_serial_value = mp.pn,
            //                child_serial = p.child_serial,
            //                child_serial_value = mc.pn,
            //                quantity = p.quantity,
            //                role = p.role,
            //                transdatetime = p.TransDateTime.ToString(ParameterConstant.DateTimeFormat)
            //            };
            //Expression<Func<AssemblyMaintenance, bool>> Funline = f => true;
            //Expression<Func<AssemblyMaintenance, bool>> Funstation = f => true;
            //Expression<Func<AssemblyMaintenance, bool>> Funserialnumber = f => true;
            //Expression<Func<AssemblyMaintenance, bool>> Funparentserial = f => true;
            //Expression<Func<AssemblyMaintenance, bool>> Funchildserial = f => true;
            //if (lineid > 0)
            //    Funline = f => f.line == lineid;
            //if (!string.IsNullOrEmpty(serial_number) && serial_number != "0")
            //    Funserialnumber = f => f.serial_number==serial_number;
            //if (!string.IsNullOrEmpty(parent_serial))
            //    Funparentserial = f => (f.parent_serial_value == parent_serial || f.child_serial_value == parent_serial);
            //if (!string.IsNullOrEmpty(child_serial))
            //    Funchildserial = f => f.child_serial_value==child_serial;
            //if (stationid>0)
            //    Funstation = f => f.station == stationid;
            //var predicate = Funline.And(Funserialnumber).And(Funparentserial).And(Funchildserial).And(Funchildserial).And(Funstation);

            //var totalCount = query.Count(predicate);
            //var entities = query.Where(predicate).OrderByDescending(q => q.id).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();
            //return new PagedCollectionResult<AssemblyMaintenance>(entities, totalCount);
        }

        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="assemblyMaintenance"></param>
        /// <param name="projectid"></param>
        /// <returns></returns>
        public CommonImportResult ImportAssemblyMaintenances(IEnumerable<AssemblyMaintenanceTemplate> assemblyMaintenance, int projectid)
        {
            var AssemblyMaintenanceLists = assemblyMaintenance.ToList();
            var entities = new List<SigerTrAssemblyMaintenance>();

            var errors = new List<string>();
            var rowIndex = 1;
            foreach (var p in AssemblyMaintenanceLists)
            {
                rowIndex++;
                var linemodel = accDbContext.siger_project_level_section.FirstOrDefault(t => t.title == p.linename && t.projectid == projectid && t.status == (int)RowState.Valid);
                var stationmodel = accDbContext.siger_project_level_section.FirstOrDefault(t => t.title == p.stationname && t.projectid == projectid && t.status == (int)RowState.Valid);
                var mpmodel = accDbContext.siger_tr_materials.FirstOrDefault(t => t.pn == p.parent_serial && t.projectId == projectid && t.status == (int)RowState.Valid);
                var mcmodel = accDbContext.siger_tr_materials.FirstOrDefault(t => t.pn == p.child_serial && t.projectId == projectid && t.status == (int)RowState.Valid);
                var sncheck = accDbContext.siger_project_product.FirstOrDefault(t => t.code == p.serial_number && t.status == (int)RowState.Valid && t.projectid == projectid);


                if (linemodel == null)
                    errors.Add($"{rowIndex},{(int)RequestEnum.LineError}");

                if (stationmodel == null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.StationError}");
                }
                if (mpmodel == null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.ParentPnNotExsit}");
                }
                if (mcmodel == null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.SonPnError}");
                }
                if (sncheck == null)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.ProductidNotNull}");
                }
                else
                {
                    var snmodel = accDbContext.siger_tr_assembly_maintenance.FirstOrDefault(t => t.serial_number == sncheck.code &&
                            t.status == (int)RowState.Valid && t.projectId == projectid);
                    if (snmodel != null)
                    {
                        errors.Add($"{rowIndex},{(int)RequestEnum.ProductidExist}");
                    }
                }
                var repeatmodel = AssemblyMaintenanceLists.Where(t => t.serial_number == p.serial_number);
                if (repeatmodel.Any() && repeatmodel.Count() > 1)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.ProductidExist}");
                }
                if (string.IsNullOrWhiteSpace(p.quantity) || p.quantity.ToInt() <= 0)
                {
                    errors.Add($"{rowIndex},{(int)RequestEnum.CountError}");
                }
            }

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

            foreach (var item in AssemblyMaintenanceLists)
            {
                //if (entity == null && typeEntity != null)检测字段值是否唯一,待做
                //{
                var linemodel = accDbContext.siger_project_level_section.FirstOrDefault(t => t.title == item.linename && t.projectid==projectid&&t.status==(int)RowState.Valid);
                var stationmodel = accDbContext.siger_project_level_section.FirstOrDefault(t => t.title == item.stationname && t.projectid == projectid && t.status == (int)RowState.Valid);
                var mpmodel = accDbContext.siger_tr_materials.FirstOrDefault(t => t.pn == item.parent_serial && t.projectId == projectid && t.status == (int)RowState.Valid);
                var mcmodel = accDbContext.siger_tr_materials.FirstOrDefault(t => t.pn == item.child_serial && t.projectId == projectid && t.status == (int)RowState.Valid);
                var productmodel = accDbContext.siger_project_product.FirstOrDefault(t => t.code == item.serial_number && t.projectid == projectid && t.status == (int)RowState.Valid);
                if (linemodel != null && stationmodel != null && mpmodel != null && mcmodel != null)
                {
                    var assemblyMaintenanceEntity = new SigerTrAssemblyMaintenance
                    {
                        projectId = projectid,
                        line = linemodel.id,
                        station = stationmodel.id,
                        serial_number = productmodel.code ?? "",
                        parent_serial = mpmodel.id,
                        parent_serial_pn = mpmodel.pn ?? "",
                        child_serial = mcmodel.id,
                        child_serial_pn = mcmodel.pn ?? "",
                        quantity = item.quantity.ToInt(),
                        role = item.role,
                        TransDateTime = DateTime.Now
                    };
                    entities.Add(assemblyMaintenanceEntity);
                }
            }
            try
            {
                accDbContext.siger_tr_assembly_maintenance.AddRange(entities);
                accDbContext.SaveChanges();
                return new CommonImportResult(1, "1");
            }
            catch
            {
                throw;
            }
        }

        public IEnumerable<AssemblyMaintenance> GetDataList(int lineid, int stationid, string serial_number, string parent_serial,
            string child_serial, int projectid)
        {
            int rowstate = (int)RowState.Valid;
            var AssemblyMaintenances =
                accDbContext.siger_tr_assembly_maintenance.Where(q => q.status == (int)RowState.Valid && q.projectId == projectid);
            var query = from p in AssemblyMaintenances
                        join m in accDbContext.siger_project_level_section
                        on new { lineid = p.line, projectids = projectid, rowstatus = rowstate }
                        equals new { lineid = m.id, projectids = m.projectid, rowstatus = m.status }
                        into linetemp
                        from m in linetemp.DefaultIfEmpty()
                        join q in accDbContext.siger_project_level_section
                        on new { stationid = p.station, projectids = projectid, rowstatus = rowstate }
                        equals new { stationid = q.id, projectids = q.projectid, rowstatus = q.status }
                        into stationtemp
                        from q in stationtemp.DefaultIfEmpty()
                        join pi in accDbContext.siger_project_product
                        on new { productid = p.serial_number, projectids = projectid, rowstatus = rowstate }
                        equals new { productid = pi.code, projectids = pi.projectid, rowstatus = pi.status }
                        into producttemp
                        from pi in producttemp.DefaultIfEmpty()
                        join mp in accDbContext.siger_tr_materials
                        on new { materialid = p.parent_serial_pn, projectids = projectid, rowstatus = rowstate }
                        equals new { materialid = mp.pn, projectids = mp.projectId, rowstatus = mp.status }
                        into mptemp
                        from mp in mptemp.DefaultIfEmpty()
                        join mc in accDbContext.siger_tr_materials
                        on new { materialid = p.parent_serial_pn, projectids = projectid, rowstatus = rowstate }
                        equals new { materialid = mc.pn, projectids = mc.projectId, rowstatus = mc.status }
                        into mctemp
                        from mc in mctemp.DefaultIfEmpty()
                        select new AssemblyMaintenance
                        {
                            id = p.id,
                            line = p.line,
                            station = p.station,
                            line_value = m.title,
                            station_value = q.title,
                            serial_number = p.serial_number,
                            serial_number_value = pi.code,
                            parent_serial = p.parent_serial,
                            parent_serial_value = mp.pn,
                            child_serial = p.child_serial,
                            child_serial_value = mc.pn,
                            quantity = p.quantity,
                            role = p.role
                        };
            Expression<Func<AssemblyMaintenance, bool>> Funline = f => true;
            Expression<Func<AssemblyMaintenance, bool>> Funstation = f => true;
            Expression<Func<AssemblyMaintenance, bool>> Funserialnumber = f => true;
            Expression<Func<AssemblyMaintenance, bool>> Funparentserial = f => true;
            Expression<Func<AssemblyMaintenance, bool>> Funchildserial = f => true;
            if (lineid > 0)
                Funline = f => f.line == lineid;
            if (!string.IsNullOrEmpty(serial_number) && serial_number != "0")
                Funserialnumber = f => f.serial_number == serial_number;
            if (!string.IsNullOrEmpty(parent_serial))
                Funparentserial = f => f.parent_serial_value == parent_serial;
            if (!string.IsNullOrEmpty(child_serial))
                Funchildserial = f => f.child_serial_value == child_serial;
            if (stationid > 0)
                Funstation = f => f.station == stationid;
            var predicate = Funline.And(Funserialnumber).And(Funparentserial).And(Funchildserial).And(Funchildserial).And(Funstation);

            var entities = query.Where(predicate).OrderByDescending(q => q.id).AsNoTracking().ToList();
            return entities;
        }
    }
}
