using BPA.MES.Base.Application.Const;
using BPA.MES.Base.Application.Entitys.Order;
using BPA.MES.Base.Application.Services.OrderService.Dtos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;

namespace BPA.MES.Base.Application.Services.OrderService.Service
{
    [ApiDescriptionSettings("订单管理", Order = 2, Name = "Order", Tag = "订单信息", KeepName = true, SplitCamelCase = true, KeepVerb = true)]
    public class OrderService : IOrderService, ITransient, IDynamicApiController
    {
        private readonly ISqlSugarClient _dbContext;
        public OrderService(ISqlSugarClient db)
        {
            _dbContext = db;
        }

        /// <summary>
        /// 分页列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<SqlSugarPagedList<OrderBaseDto>> PagedList(OrderQueryPageInput input)
        {
            var entity = await _dbContext.Queryable<OrderEntity>()
                .WhereIF(!string.IsNullOrEmpty(input.Id), a => a.Id.Contains(input.Id))
                .WhereIF(!string.IsNullOrEmpty(input.Status), a => ((int)a.Status).ToString()==input.Status)
                .Select((x) => new OrderBaseDto
                {
                    Id = x.Id.SelectAll(),
                })
                .ToPagedListAsync(input.PageIndex, input.PageSize);
            

            var orderIds= entity.Items.Select(x => x.Id);

            var itemList = await _dbContext.Queryable<OrderInfoEntity>()
                .Where(x => orderIds.Contains(x.OrderId))
                .ToListAsync();

            var list = await _dbContext.Queryable<Pztj_WorkInfoEntity>()
                .LeftJoin<Pztj_FinalsInfoEntity>((a, b) => a.FinalId == b.Id)
                .LeftJoin<ProductLineEntity>((a, b, c) => a.LineId == c.Id)
                .LeftJoin<Pztj_WorkInfoStatusEntity>((a, b, c, d) => d.Id == SqlFunc.Subqueryable<Pztj_WorkInfoStatusEntity>().Where(s => s.WorkId == a.Id).OrderByDesc(s => s.CreateTime).Select(s => s.Id))
                .LeftJoin<OrderWorkEntity>((a, b, c, d,e) =>a.Id==e.WorkId )
                .Where((a, b, c, d, e)=> orderIds.Contains(e.OrderId))
                .Select((a, b, c, d,e) => new OrderInfoBaseDto
                {
                    FinalslId=a.FinalId,
                    FinalslName=b.Name,
                    Number=string.IsNullOrEmpty(a.Number)?0:Convert.ToInt32(a.Number),
                    OrderId=e.OrderId,
                    ProductionLineId=a.LineId,
                    ProductionLineName=c.Name,
                    Id = a.Id,
                    CreateTime=a.CreateTime.ToString(),
                    Status = d.Status == null ? WorkOrderStatusEnum.Draft : d.Status
                }).ToListAsync();

          SqlSugarPagedList <OrderBaseDto> output = entity.Adapt<SqlSugarPagedList<OrderBaseDto>>();
          foreach (var item in output.Items)
          {
              item.OrderInfos= list.Where(x=>x.OrderId==item.Id).ToList();
              item.ProduceRate= list.Where(x => x.OrderId == item.Id&&x.Status== WorkOrderStatusEnum.Completed).Count();
              item.ProduceSum = itemList.Where(x => x.OrderId == item.Id).Sum(x => x.Number);
          }
            return output;
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<bool> Add(List<OrderInfoBaseDto> inputDto)
        {

            try
            {

                _dbContext.Ado.BeginTran();
                OrderEntity order = new OrderEntity();
                var res = await _dbContext.Insertable(order)
                    .IgnoreColumns(ignoreNullColumn: true)
                    .ExecuteCommandIdentityIntoEntityAsync();
                if (res)
                {
                    List<OrderInfoEntity> orderInfo = inputDto.Adapt<List<OrderInfoEntity>>();
                    orderInfo = orderInfo.GroupBy(x => x.FinalslId).Select(x => new OrderInfoEntity()
                    {
                        CreateTime = DateTime.Now,
                        FinalslId = x.Key,
                        Number = x.Sum(y => y.Number),
                    }).ToList();
                    foreach (var item in orderInfo)
                    {
                        item.Id = YitIdHelper.NextId().ToString();
                        item.OrderId = order.Id;
                    }
                    res = await _dbContext.Insertable(orderInfo)
                        .ExecuteCommandIdentityIntoEntityAsync();
                }

                _dbContext.Ado.CommitTran();
                return res;
            }
            catch (Exception ex)
            {
                _dbContext.Ado.RollbackTran();
                return false;
            }
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<bool> Update(List<OrderInfoBaseDto> inputDto)
        {
            try
            {

                _dbContext.Ado.BeginTran();
                var orderId = inputDto.Select(x => x.OrderId).First();

                //删除原来的所有
                var res = await _dbContext.Deleteable<OrderInfoEntity>(x => x.OrderId == orderId).ExecuteCommandHasChangeAsync();

                List<OrderInfoEntity> orderInfo = inputDto.Adapt<List<OrderInfoEntity>>();
                orderInfo = orderInfo.GroupBy(x => x.FinalslId).Select(x => new OrderInfoEntity()
                {
                    CreateTime = DateTime.Now,
                    FinalslId = x.Key,
                    Number = x.Sum(y => y.Number),
                }).ToList();
                foreach (var item in orderInfo)
                {
                    item.Id = YitIdHelper.NextId().ToString();
                    item.OrderId = orderId;
                }
                res = await _dbContext.Insertable(orderInfo)
                    .ExecuteCommandIdentityIntoEntityAsync();


                _dbContext.Ado.CommitTran();
                return res;
            }
            catch (Exception ex)
            {
                _dbContext.Ado.RollbackTran();
                return false;
            }
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<bool> Del(string Id)
        {

            try
            {
                _dbContext.Ado.BeginTran();

                var res = await _dbContext.Deleteable<OrderEntity>().Where(x => x.Id == Id).ExecuteCommandHasChangeAsync();
                if (res)
                {
                    res = await _dbContext.Deleteable<OrderInfoEntity>().Where(x => x.OrderId == Id).ExecuteCommandHasChangeAsync();
                }
                _dbContext.Ado.CommitTran();
                return res;
            }
            catch (Exception ex)
            {
                _dbContext.Ado.RollbackTran();
                return false;
            }
        }

        /// <summary>
        /// 获取订单的商品
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<List<OrderInfoBaseDto>> GetOrderMaterial(string OrderId)
        {

            var res = await _dbContext.Queryable<OrderInfoEntity>().Where(x => x.OrderId == OrderId)
                .Select(x => new OrderInfoBaseDto()
                {

                    Id = x.Id,
                    FinalslId = x.FinalslId,
                    Number = x.Number,
                    OrderId = x.OrderId,
                })
                .ToListAsync();
            return res;
        }


        /// <summary>
        /// 添加工单 并绑定订单
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        public async Task<bool> OrderAssociationWork(List<OrderInfoBaseDto> inputDto)
        {
            var result = false;
            var orderId = inputDto.Select(x => x.OrderId).First();
            //验证
            VerifyOrderProduct(inputDto);
            _dbContext.Ado.BeginTran();

            try
            {
                foreach (var item in inputDto)
                {
                    Pztj_WorkInfoEntity entity = new Pztj_WorkInfoEntity()
                    {
                        CreateTime = DateTime.Now,
                        FinalId = item.FinalslId,
                        LineId = item.ProductionLineId,
                        Name = "",
                        Number = item.Number.ToString(),

                    };
                    var res=  await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
                    Pztj_WorkInfoStatusEntity pztj_WorkInfoStatusEntity = new()
                    {
                        Status = WorkOrderStatusEnum.Draft,
                        WorkId = entity.Id
                    };
                    if (res >0)
                    {
                       res= await _dbContext.Insertable(pztj_WorkInfoStatusEntity).IgnoreColumns(true).ExecuteCommandAsync();
                       if (res>0)
                       {
                           res = await _dbContext.Insertable(new OrderWorkEntity()
                           {
                               OrderId = orderId,
                               WorkId=entity.Id
                           }).IgnoreColumns(true).ExecuteCommandAsync();
                           if (res>0)
                           {
                               var order=_dbContext.Queryable< OrderEntity >().First(x=>x.Id==orderId);
                               order.Status = OrderStatusEnum.Ongoing;
                                 //修改订单状态
                               res =await _dbContext.Updateable(order).ExecuteCommandAsync();
                               if (res<=0)
                               {
                                   _dbContext.Ado.RollbackTran();
                                   return false;
                               }

                           }
                           else
                           {
                               _dbContext.Ado.RollbackTran();
                               return false;
                           }
                       }
                       else 
                       {
                           _dbContext.Ado.RollbackTran();
                           return false;
                       }
                    }
                    else
                    {
                        _dbContext.Ado.RollbackTran();
                        return false;
                    }
                }
            }
            catch
            {
                _dbContext.Ado.RollbackTran();
                throw Oops.Bah("添加失败!");
            }
            _dbContext.Ado.CommitTran();
            return true;
        }

        /// <summary>
        /// 生成工单时验证成品数量
        /// </summary>
        /// <param name="inputDto"></param>
        private void VerifyOrderProduct(List<OrderInfoBaseDto> inputDto)
        {
            var orderId = inputDto.Select(x => x.OrderId).First();
            var data=_dbContext.Queryable<OrderInfoEntity, Pztj_FinalsInfoEntity>((a,b)=>new JoinQueryInfos(
                JoinType.Left,a.FinalslId==b.Id
                )).Where((a,b)=>a.OrderId==orderId).
                Select((a,b)=>new
                {
                    orderId = a.OrderId,
                    ProductId = a.FinalslId,
                    productName = b.Name,
                    a.Number
                }).ToList();
            foreach (var item in data)
            {
                var productCount = inputDto.Where(x => x.FinalslId == item.ProductId).Sum(x => x.Number);
                var count= item.Number - productCount;
                if (count<0)
                {
                    throw Oops.Bah($"{item.productName}成品生成工单数量大于订单数量，多【{System.Math.Abs(count)}】");
                }

                if (count>0)
                {
                    throw Oops.Bah($"{item.productName}成品生成工单数量小于订单数量，差【{count}】");
                }

            }
        }

        /// <summary>
        /// 获取成品剩余制作数量
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<OrderWorkLimit>> GetFinalslLImit(string OrderId)
        {
            var result = new List<OrderWorkLimit>();
            var orderInfo=_dbContext.Queryable<OrderInfoEntity>().Where(x=>x.OrderId==OrderId).ToList();

            var list=_dbContext.Queryable<OrderWorkEntity , Pztj_WorkInfoEntity>((a,b)=>new JoinQueryInfos(
                JoinType.Left,a.WorkId==b.Id))
                .Where((a, b) => a.OrderId==OrderId)
                .Select((a,b)=>new OrderWorkLimit()
                {
                    FinalslId=b.FinalId,
                    Limit=0
                }).ToList();

            foreach (var item in orderInfo)
            {
                var data=list.Where(x=>x.FinalslId==item.FinalslId).ToList();

                result.Add(new OrderWorkLimit()
                {
                    FinalslId=item.FinalslId,
                    Limit=item.Number-data.Sum(x=>x.Limit),
                });
            }
            return result;

        }

        [HttpGet]
        public Task<bool> CodeFirst()
        {
            var types = Assembly.Load("BPA.MES.Base.Application").GetTypes()
                .Where(x => x.GetCustomAttribute<SugarTable>() != null
                            && x.Namespace == "BPA.MES.Base.Application.Entitys.Order").ToArray();
            _dbContext.CodeFirst.InitTables(types);
            return Task.FromResult(true);
        }
    }
}
