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

namespace Siger.Middlelayer.IMSRepository.Repositories
{
    public class ProjectIMSDetectionRecordRepository : RepositoryBase<Entities.ProjectIMSDetectionRecordEntity>, IProjectIMSDetectionRecordRepository
    {
        private readonly ApiIMSDbContext _context;
        public ProjectIMSDetectionRecordRepository(ApiIMSDbContext context) : base(context)
        {
            _context = context;
        }

        public IPagedCollectionResult<ResponeToollifeDetectionRecord> GetPagedList(RequestProjectIMSDetectionRecord req)
        {
            var query = from q in _context.ProjectIMSDetectionRecordEntities
                        join t in _context.siger_project_ims_tool on q.ToolId equals t.id
                        join m in _context.siger_tr_materials on t.material_id equals m.id
                        //join test in _context.ProjectIMSTestEntities on q.OrderNumber equals test.OrderNumber into temp
                        //from test in temp.DefaultIfEmpty()
                        where q.Status == (int)RowState.Valid && q.Projectid == req.ProjectId
                        select new ResponeToollifeDetectionRecord
                        {
                            tool_id = t.id,
                            category_id = t.category_id,
                            category_name = t.category_name,
                            material_id = t.material_id,
                            material_name = m.name,
                            part_no = t.part_no,
                            state = q.State,
                            need_test = t.need_test,
                            need_detection = t.need_detection,
                            //in_time = m.transdatetime,
                            OrderNumber = q.OrderNumber,
                            tool_number = t.number,
                            tool_name = t.name,
                            inspect_time = q.inspect_time,
                            inspector = q.inspector,
                            result = q.result,
                            stock_id = q.StockId,
                            ToolType = q.ToolType,
                            serial_number = q.serial_number,
                            manage_model = q.manage_model,
                            //test_result = test.Result.ToStr()
                        };
            List<ProjectIMSDetectionReturnEntity> returnData = null;
            Expression<Func<ResponeToollifeDetectionRecord, bool>> conditionState = q => true;
            if (!string.IsNullOrEmpty(req.state))
            {
                if (req.state.ToInt() == 0)
                {
                    returnData = _context.ProjectIMSDetectionReturnEntity.Where(f => f.Projectid == req.ProjectId && f.Status != 0).ToList();
                    conditionState = q => returnData.Select(s => s.order_number).Contains(q.OrderNumber);
                }
                else
                {
                    conditionState = q => (int)q.state == req.state.ToInt();
                }
            }
            Expression<Func<ResponeToollifeDetectionRecord, bool>> conditionStates = q => true;
            if (!string.IsNullOrEmpty(req.states))
            {
                var states = req.states.Split(',').Distinct().Where(f => !string.IsNullOrEmpty(f)).ToList();
                if (states.Any())
                {
                    conditionStates = q => states.Contains(((int)q.state).ToStr());
                }
            }
            Expression<Func<ResponeToollifeDetectionRecord, bool>> conditionTool_type = q => true;
            if (!string.IsNullOrEmpty(req.tool_type))
            {
                conditionTool_type = q => q.category_name.StartsWith(req.tool_type);
            }
            Expression<Func<ResponeToollifeDetectionRecord, bool>> conditionTool_number = q => true;
            if (!string.IsNullOrEmpty(req.tool_number))
            {
                conditionTool_number = q => q.tool_number.StartsWith(req.tool_number);
            }
            Expression<Func<ResponeToollifeDetectionRecord, bool>> conditionTool_name = q => true;
            if (!string.IsNullOrEmpty(req.tool_name))
            {
                conditionTool_name = q => q.tool_name.StartsWith(req.tool_name);
            }
            Expression<Func<ResponeToollifeDetectionRecord, bool>> conditionNeedTest = q => true;
            if (!string.IsNullOrEmpty(req.need_test))
            {
                var need_test = req.need_test.ToInt();
                conditionNeedTest = q => q.need_test == need_test;
            }
            Expression<Func<ResponeToollifeDetectionRecord, bool>> conditionResult = q => true;
            if (!string.IsNullOrEmpty(req.result))
            {
                var result = req.result.ToInt();
                conditionResult = q => q.result == result;
            }
            Expression<Func<ResponeToollifeDetectionRecord, bool>> conditionTestResult = q => true;
            if (!string.IsNullOrEmpty(req.testResult))
            {
                var result = _context.ProjectIMSTestEntities.Where(f => f.Projectid == req.ProjectId && f.Status != 0 && f.Result == req.testResult.ToInt());
                conditionTestResult = q => result.Select(s => s.OrderNumber).ToList().Contains(q.OrderNumber);
            }
            Expression<Func<ResponeToollifeDetectionRecord, bool>> conditionTime = q => true;
            if (req.inspect_start != 0 && req.inspect_end != 0)
            {
                conditionTime = q => q.inspect_time >= req.inspect_start && q.inspect_time <= req.inspect_end;
            }
            var predicate = conditionState.And(conditionTool_type).And(conditionTool_number).And(conditionTool_name).And(conditionStates)
                .And(conditionNeedTest).And(conditionResult).And(conditionTime).And(conditionTestResult);
            int totalCount = query.Count(predicate);
            List<ResponeToollifeDetectionRecord> entities;
            if (req.Page == 0)
            {
                entities = query.Where(predicate).OrderByDescending(o=>o.inspect_time).AsNoTracking().ToList();
            }
            else
            {
                entities = query.Where(predicate).OrderByDescending(o => o.inspect_time).Skip((req.Page - 1) * req.PageSize).Take(req.PageSize).AsNoTracking().ToList();
            }
            var user = _context.siger_project_user.Where(f => f.projectid == req.ProjectId && f.status != 0);
            foreach (var entity in entities)
            {
                var supplier = (from ms in _context.siger_tr_material_supplier
                                join bu in _context.siger_wms_bussinese_contacts on ms.supplier_id equals bu.id
                                where ms.material_id == entity.material_id
                                select bu).FirstOrDefault();
                entity.supplier_name = supplier?.name ?? "";
                entity.inspector_name = user.FirstOrDefault(f => f.mid == entity.inspector)?.name ?? "";
                if (returnData != null && returnData.Any())
                {
                    entity.reason = returnData.FirstOrDefault(f => f.order_number == entity.OrderNumber)?.reason ?? "";
                    entity.return_time = returnData.FirstOrDefault(f => f.order_number == entity.OrderNumber)?.CreateTime ?? default(DateTime);
                }
                var stockData = _context.siger_wms_stock.FirstOrDefault(f => f.id == entity.stock_id);
                if (stockData != null)
                {
                    var storage = _context.siger_wms_storage_location.FirstOrDefault(f => f.id == stockData.storage_location_id);
                    entity.location = storage?.name ?? "";
                    entity.storage_location_id = stockData.storage_location_id;
                    entity.storageid = storage?.storageid ?? 0;
                }
                if (entity.manage_model == managemodel.No)
                {
                    entity.in_time = _context.siger_wms_stock_detail.FirstOrDefault(f => f.no == entity.serial_number)?.updatetime ?? default(DateTime);
                }
                else
                {
                    entity.in_time = _context.siger_wms_stock_detail.FirstOrDefault(f => f.batch == entity.serial_number)?.updatetime ?? default(DateTime);
                }
                entity.test_result= _context.ProjectIMSTestEntities.Where(f => f.Projectid == req.ProjectId && f.Status != 0 && f.OrderNumber==entity.OrderNumber).OrderByDescending(o=>o.Id)
                    .FirstOrDefault()?.Result.ToStr()??"";
            }
            return new PagedCollectionResult<ResponeToollifeDetectionRecord>(entities, totalCount);
        }

        public bool ChangeLocation(int stockIDs, int ProjectId, int UserId, int to)
        {
            var data = _context.siger_wms_stock.Where(f => stockIDs == f.id && f.projectid == ProjectId && f.status == (int)RowState.Valid).ToList();
            var locationdata = _context.siger_wms_storage_location.FirstOrDefault(f => f.id == to && f.status == (int)RowState.Valid);
            var pids = _context.siger_wms_storage_type.Where(f => f.status == (int)RowState.Valid && f.projectid == ProjectId).Select(f => f.parentid);

            if (locationdata == null)
            {
                throw new BadRequestException(RequestEnum.LocationError);
            }
            var endstorage = _context.siger_wms_storage.FirstOrDefault(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.id == locationdata.storageid);
            if (endstorage == null)
            {
                throw new BadRequestException(RequestEnum.StorageError);
            }
            var username = _context.siger_project_user.FirstOrDefault(f => f.projectid == ProjectId && f.status != 0 && f.mid == UserId)?.name ?? "";
            foreach (var item in data)
            {
                var tmpLocation = _context.siger_wms_storage_location.FirstOrDefault(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.id == item.storage_location_id);
                if (tmpLocation == null)
                {
                    continue;
                }
                if (tmpLocation.storageid != endstorage.id)
                {
                    throw new BadRequestException(RequestEnum.StorageDeny);
                }
                var tmp = new siger_wms_stock_detail
                {
                    type = (int)traceType.LocationChange,
                    inventory = item.material_id,
                    inventoryName = item.material_name,
                    inventorySN = item.material_pn,
                    inventorySpec = item.material_spec,
                    locationid = item.storage_location_id,
                    locationname = locationdata.name,
                    batch = item.batch_number,
                    no = item.serial_number,
                    userid = UserId,
                    username = username.ToString(),
                    updatetime = DateTime.Now,
                    state = (int)RowState.Valid,
                    projectid = ProjectId,
                    allqty = item.quantity,
                    qty = item.quantity,
                    businessid = item.businessid,
                    businessName = _context.siger_wms_bussinese_contacts.FirstOrDefault(f => f.id == item.businessid)?.name ?? ""
                };
                _context.siger_wms_stock_detail.Add(tmp);
                item.storage_location_id = to;
                item.update_time = DateTime.Now;
                item.updator = UserId;
                _context.siger_wms_stock.Update(item);
            }
            if (_context.SaveChanges() > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
