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

namespace Siger.Middlelayer.TpmRepository.Repositories
{
    internal class SparepartRecordRepository : TpmRepositoryBase<siger_project_sparepart_record>, ISparepartRecordRepository
    {
        private readonly ApiTpmDbContext _context;
        public SparepartRecordRepository(ApiTpmDbContext context) : base(context)
        {
            _context = context;
        }

        public IPagedCollectionResult<SparepartRecord> GetPagedList(int startTime, int endTime, string keyword,
            string is_standard, string is_substitute, int skutype, int inStockType, int outStockType,
            string link, List<int> machineIds,
            int sparepart, int projectid, int page, int pagesize, bool getAll = false)
        {
            IQueryable<siger_project_sparepart_record> query;
            if (machineIds.Any())
            {
                query = _context.siger_project_sparepart_record.Where(q => q.projectid == projectid && machineIds.Contains(q.machineid));
            }
            else
            {
                query = _context.siger_project_sparepart_record.Where(q => q.projectid == projectid);
            }
            var querylist = from q in query
                            join u1 in _context.siger_project_user on q.create_mid equals u1.mid into user1
                            from u1 in user1.DefaultIfEmpty()
                            join u2 in _context.siger_project_user on q.operate_mid equals u2.mid.ToString() into user2
                            from u2 in user2.DefaultIfEmpty()
                            join sp1 in _context.siger_project_sparepart on q.sparepartid equals sp1.id into spart1
                            from sp1 in spart1.DefaultIfEmpty()
                            join ma1 in _context.siger_project_machine on q.machineid equals ma1.id into machine1
                            from ma1 in machine1.DefaultIfEmpty()
                            select new SparepartRecord
                            {
                                id = q.id,
                                record_code = q.record_code,
                                uname = u1 != null ? u1.name : "",
                                operate_name = u2 != null ? u2.name : "",
                                stitle = sp1.title,
                                mtitle = ma1 != null ? ma1.title : "",
                                param = sp1.param,
                                code = sp1.code,
                                is_standard = sp1.is_standard,
                                price = sp1.price,
                                is_substitute = sp1.is_substitute,
                                create_time = q.create_time,
                                type = q.type,
                                is_common = sp1.is_common,
                                IO_type = q.IO_type,
                                relation_repair = q.relation_repair,
                                remark = q.remark,
                                last_sku = q.last_sku,
                                sum_price = q.sum_price,
                                number = q.number,
                                order_code = q.order_code,
                                machineId = q.machineid,
                            };

            Expression<Func<SparepartRecord, bool>> starttimeExpression = q => true;
            if (startTime != 0)
            {
                starttimeExpression = q => q.create_time >= startTime;
            }

            Expression<Func<SparepartRecord, bool>> endtimeExpression = q => true;
            if (endTime != 0)
            {
                endtimeExpression = q => q.create_time <= endTime;
            }

            Expression<Func<SparepartRecord, bool>> keywordExpression = q => true;
            if (!string.IsNullOrEmpty(keyword))
            {
                keywordExpression = q =>
                    (q.code.Contains(keyword) || q.stitle.Contains(keyword) || q.param.Contains(keyword) ||
                    q.record_code.Contains(keyword));
            }
            Expression<Func<SparepartRecord, bool>> isstandardExpression = q => true;
            if (!string.IsNullOrWhiteSpace(is_standard))
            {
                isstandardExpression = q => q.is_standard == is_standard.ToInt();
            }
            Expression<Func<SparepartRecord, bool>> issubstituteExpression = q => true;
            if (!string.IsNullOrWhiteSpace(is_substitute))
            {
                issubstituteExpression = q => q.is_substitute == is_substitute.ToInt();
            }
            Expression<Func<SparepartRecord, bool>> skutypeExpression = q => true;
            if (skutype != 0)
            {
                skutypeExpression = q => q.type == skutype;
                if (inStockType != 0)
                {
                    skutypeExpression = q => q.type == skutype && q.IO_type == inStockType;
                }
                if (outStockType != 0)
                {
                    skutypeExpression = q => q.type == skutype && q.IO_type == outStockType;
                }
            }
            Expression<Func<SparepartRecord, bool>> linkExpression = q => true;
            if (!string.IsNullOrWhiteSpace(link))
            {
                linkExpression = q => q.relation_repair == link.ToInt();
            }
            var predicate = starttimeExpression.And(endtimeExpression).And(keywordExpression).And(isstandardExpression)
                .And(issubstituteExpression).And(skutypeExpression).And(linkExpression);

            if (getAll)
            {
                var entities = querylist.Where(predicate).OrderByDescending(q => q.create_time).AsNoTracking().ToList();

                return new PagedCollectionResult<SparepartRecord>(entities, 0);
            }
            else
            {
                var totalCount = querylist.Count(predicate);
                var entities = querylist.Where(predicate).OrderByDescending(q => q.create_time).Skip((page - 1) * pagesize).Take(pagesize).AsNoTracking().ToList();

                return new PagedCollectionResult<SparepartRecord>(entities, totalCount);
            }
        }

        public IEnumerable<ResponseGetSparepartOut> GetListBySparepartOutType(List<int> sparepartout, int type, string repairid, int projectid)
        {
            var query = _context.siger_project_sparepart_record.Where(q => q.projectid == projectid && q.relation_repair == 1
                 && q.type == 1 && q.IO_type == type && q.order_code == repairid && sparepartout.Contains(q.sparepartid));
            var querylist = (from q in query
                             join u1 in _context.siger_project_user on q.create_mid equals u1.mid into user1
                             from u1 in user1.DefaultIfEmpty()
                             join sp1 in _context.siger_project_sparepart on q.sparepartid equals sp1.id into spart1
                             from sp1 in spart1.DefaultIfEmpty()
                             select new ResponseGetSparepartOut
                             {
                                 id = q.id,
                                 record_code = q.record_code,
                                 operate_name = u1 != null ? u1.name : "",
                                 stitle = sp1.title,
                                 param = sp1.param,
                                 code = sp1.code,
                                 is_standard = sp1 != null ? sp1.is_standard : 0,
                                 price = sp1 != null ? sp1.price : 0,
                                 is_substitute = sp1 != null ? sp1.is_substitute : 0,
                                 create_time = UnixTimeHelper.ConvertIntDateTime(q.create_time),
                                 type = q.type,
                                 is_common = sp1 != null ? sp1.is_common : 0,
                                 io_type = q.IO_type,
                                 relation_repair = q.relation_repair,
                                 remark = q.remark,
                                 sku = sp1.sku,
                                 last_sku = q.last_sku,
                                 sum_price = q.sum_price,
                                 number = q.number,
                                 order_code = q.order_code,
                                 machineid = q.machineid,
                                 sparepartid = q.sparepartid,
                                 create_mid = q.create_mid,
                                 supplier = q.supplier,
                                 operate_mid = u1.mid > 0 ? u1.mid : 0,
                                 is_exchange = q.is_exchange
                             }).GroupBy(t => t.sparepartid).Select(t => t.FirstOrDefault()).ToList();
            return querylist.OrderByDescending(t => t.create_time).ThenByDescending(x => x.id);
        }
    }
}
