using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using TouchSocket.Core;
using WCS.BLL.Config;
using WCS.BLL.DbModels;
using WCS.BLL.HardWare;
using WCS.BLL.Manager;
using WCS.BLL.Services.IService;
using WCS.DAL;
using WCS.DAL.Db;
using WCS.DAL.DbModels;
using WCS.Model;
using WCS.Model.ApiModel;
using WCS.Model.ApiModel.BatchBindMatDetail;
using WCS.Model.ApiModel.InOutRecord;
using WCS.Model.ApiModel.MatBaseInfo;
using WCS.Model.ApiModel.MatDetailCurrentInfo;
using WCS.Model.ApiModel.MatDetailHistoryInfo;
using WCS.Model.ApiModel.StoreInfo;
using WCS.Model.ApiModel.User;

namespace WCS.BLL.Services.Service
{
    public class BatchBindMatDetailService : IBatchBindMatDetailService
    {
        /// <summary>
        /// 按照工位号获取绑定明细
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<PageQueryResponse<MatDetailCurrentInfoModel>> GetMatDetailCurrentInfosByStationCode(GetMatDetailCurrentInfosByStationCodeRequest request)
        {
            try
            {
                var recordsQueryable = DbHelp.db.Queryable<MatDetailCurrentInfo>()
                                                .LeftJoin<ShelfInfo>((mci, si) => mci.ShelfId == si.Id)
                                                .LeftJoin<LocationInfo>((mci, si, li) => (si.TransStatus == TransStatusEnum.静止 && si.CurrentLocationId == li.Id)
                                                || (si.TransStatus == TransStatusEnum.运输中 && si.DestinationLocationId == li.Id))
                                                .Where((mci, si, li) => !string.IsNullOrEmpty(mci.StationCode))
                                                .WhereIF(request.OrderTypeId != null && request.OrderTypeId != 0, (mci, si, li) => mci.OrderTypeId == request.OrderTypeId)
                                                .WhereIF(!string.IsNullOrEmpty(request.ShelfCode), (mci, si, li) => si.ShelfCode.Contains(request.ShelfCode))

                                                .WhereIF(!string.IsNullOrEmpty(request.StationCode) && request.StationCode.ToLower() != "admin", (mci, si, li) => mci.StationCode.Contains(request.StationCode))
                                                .Select((mci, si, li) => new MatDetailCurrentInfoModel()
                                                {
                                                    Id = mci.Id,
                                                    ShelfId = mci.ShelfId,
                                                    ShelfCode = mci.ShelfCode,
                                                    ShelfType = mci.ShelfType,

                                                    LocationArea = li.LocationArea,
                                                    LocationCode = li.LocationCode,

                                                    MatCode = mci.MatCode,
                                                    MatName = mci.MatName,
                                                    MatBatch = mci.MatBatch,
                                                    MatSpec = mci.MatSpec,
                                                    MatUnit = mci.MatUnit,
                                                    MatCustomer = mci.MatCustomer,
                                                    MatQty = mci.MatQty,
                                                    MatSupplier = mci.MatSupplier,

                                                    OrderTypeId = mci.OrderTypeId,
                                                    OrderTypeName = mci.OrderTypeName,
                                                    OrderNumber = mci.OrderNumber,

                                                    StationCode = mci.StationCode,
                                                    ModifyUser = mci.ModifyUser,
                                                    ModifyTime = mci.ModifyTime
                                                });

                //分页
                var totalCount = await recordsQueryable.CountAsync();
                var records = await recordsQueryable
                                    .OrderByDescending(mci => mci.Id)
                                    .Skip((request.PageNumber - 1) * request.PageSize).Take(request.PageSize)
                                    .ToListAsync();
                //生成序号
                for (int i = 0; i < records.Count; i++)
                {
                    records[i].RowNumber = (request.PageNumber - 1) * request.PageSize + i + 1;
                }
                return new PageQueryResponse<MatDetailCurrentInfoModel>()
                {
                    Code = 200,
                    Message = $"success",
                    Data = new PageQueryResponseData<MatDetailCurrentInfoModel>()
                    {
                        TotalCount = totalCount,
                        MaxPage = request.PageSize == 0 ? 0 : (int)Math.Ceiling((decimal)totalCount / request.PageSize),
                        Count = records.Count,
                        Lists = records.ToList()
                    }
                };
            }
            catch (Exception ex)
            {
                return new PageQueryResponse<MatDetailCurrentInfoModel>()
                {
                    Code = 300,
                    Message = $"操作失败:{ex.Message}",
                };
            }
        }

        public async Task<ResponseCommon<object>> updateMatDetailCurrentInfo(AddLocaionInfoRequest<MatDetailCurrentInfo> request)
        {
            try
            {
                var matDetailCurrentInfo = await DbHelp.db.Queryable<MatDetailCurrentInfo>()     //.Where(t => t.MatDetailCurrentCode == request.MatDetailCurrentInfo.MatDetailCurrentCode)
                                                          .Where(t => t.Id == request.LocationInfo.Id)
                                                          .FirstAsync();
                if (matDetailCurrentInfo == null)
                {
                    return new ResponseCommon<Object>
                    {
                        Code = 205,
                        Message = $"更新位置信息失败：此条数据不存在，请确认！",
                        Data = null
                    };
                }
                DbHelp.db.BeginTran();
                //新增数据修改记录表
                var historyInfo = new MatDetailHistoryInfo()
                {
                    ShlefId = matDetailCurrentInfo.ShelfId,
                    ShelfType = matDetailCurrentInfo.ShelfType,
                    ShelfCode = matDetailCurrentInfo.ShelfCode,

                    MatCode = matDetailCurrentInfo.MatCode,
                    MatName = matDetailCurrentInfo.MatName,
                    MatBatch = matDetailCurrentInfo.MatBatch,
                    MatSpec = matDetailCurrentInfo.MatSpec,
                    MatCustomer = matDetailCurrentInfo?.MatCustomer,
                    MatSupplier = matDetailCurrentInfo?.MatSupplier,

                    BeforeQty = matDetailCurrentInfo.MatQty,
                    AfterQty = request.LocationInfo.MatQty,

                    ModifyTime = DateTime.Now,
                    ModifyUser = request.UserName,
                    RecordType = RecordTypeEnum.修改,
                    FunctionType = FunctionTypeEnum.客户端物料绑定,
                };
                await DbHelp.db.Insertable(historyInfo).ExecuteCommandAsync();
                //更新货架存量数据
                matDetailCurrentInfo.MatQty = request.LocationInfo.MatQty;
                matDetailCurrentInfo.ModifyUser = request.UserName;
                matDetailCurrentInfo.ModifyTime = DateTime.Now;
                var rowNum = await DbHelp.db.Updateable(matDetailCurrentInfo).ExecuteCommandAsync();
                if (rowNum == 0)
                {
                    DbHelp.db.RollbackTran();
                    return new ResponseCommon<Object>
                    {
                        Code = 201,
                        Message = $"更新货架存量信息失败：请重试！",
                        Data = null
                    };
                }
                else
                {
                    DbHelp.db.CommitTran();
                    DataProcessManager.UpdateShelfStatus();
                    return new ResponseCommon<Object>
                    {
                        Code = 200,
                        Message = $"更新货架存量信息成功！",
                        Data = null
                    };
                }
            }
            catch (Exception ex)
            {
                DbHelp.db.RollbackTran();
                var response = new ResponseCommon<Object>
                {
                    Code = 300,
                    Message = $"更新货架存量信息失败:{ex.Message}",
                    Data = null
                };
                return response;
            }
        }

        public async Task<ResponseCommon<object>> deleteMatDetailCurrentInfo(DeleteInfosRequest request)
        {
            //先查询出具体的数据
            var matDetailCurrentInfos = await DbHelp.db.Queryable<MatDetailCurrentInfo>()
                                               .Where(t => request.needDeleteIds.Contains(t.Id))
                                               .ToListAsync();
            //执行删除
            try
            {
                DbHelp.db.BeginTran();
                //新增数据删除记录
                foreach (var matDetailCurrentInfo in matDetailCurrentInfos)
                {
                    var historyInfo = new MatDetailHistoryInfo()
                    {
                        ShlefId = matDetailCurrentInfo.ShelfId,
                        ShelfType = matDetailCurrentInfo.ShelfType,
                        ShelfCode = matDetailCurrentInfo.ShelfCode,

                        MatCode = matDetailCurrentInfo.MatCode,
                        MatName = matDetailCurrentInfo.MatName,
                        MatBatch = matDetailCurrentInfo.MatBatch,
                        MatSpec = matDetailCurrentInfo.MatSpec,
                        MatCustomer = matDetailCurrentInfo?.MatCustomer,
                        MatSupplier = matDetailCurrentInfo?.MatSupplier,

                        BeforeQty = matDetailCurrentInfo.MatQty,
                        AfterQty = 0,//删除数据 为0

                        ModifyTime = DateTime.Now,
                        ModifyUser = request.UserName,
                        RecordType = RecordTypeEnum.删除,
                        FunctionType = FunctionTypeEnum.客户端物料绑定,
                    };
                    await DbHelp.db.Insertable(historyInfo).ExecuteCommandAsync();
                }
                var deleteRows = await DbHelp.db.Deleteable(matDetailCurrentInfos).ExecuteCommandAsync();

                DbHelp.db.CommitTran();
                DataProcessManager.UpdateShelfStatus();
                return new ResponseCommon<Object>
                {
                    Code = 200,
                    Message = $"已删除{deleteRows}条数据！",
                    Data = null
                };
            }
            catch (Exception ex)
            {
                DbHelp.db.RollbackTran();
                var response = new ResponseCommon<Object>
                {
                    Code = 300,
                    Message = $"操作失败:{ex.Message}",
                    Data = null
                };
                return response;
            }
        }

        /// <summary>
        /// 批量导入物料绑定关系
        /// </summary>
        /// <param name="lists"></param>
        /// <param name="userName"></param>
        /// <param name="deviceType"></param>
        /// <returns></returns>
        public async Task<ResponseCommon<List<string>>> importMatDetailCurrentInfo(List<MatDetailCurrentInfoImportModel> lists, string userName, string deviceType, string stationCode)
        {
            #region 校验
            ////工位校验 工位是否有货架校验
            //var station = await DbHelp.db.Queryable<LocationInfo>()
            //                              .Where(t => t.LocationCode == stationCode && t.IsEnable == true)
            //                              .FirstAsync();
            //if (station == null)
            //{
            //    return new ResponseCommon<List<string>>()
            //    {
            //        Code = 201,
            //        Message = $"导入失败:工位[{stationCode}]不存在或已被禁用！",
            //        Data = null,
            //    };
            //}

            //var shelfInfo = await DbHelp.db.Queryable<ShelfInfo>()
            //                               .Where(t => (t.TransStatus == TransStatusEnum.静止 && t.CurrentLocationId == station.Id) ||
            //                                            t.TransStatus == TransStatusEnum.运输中 && t.DestinationLocationId == station.Id)
            //                               .Where(t => t.IsEnable)
            //                                .FirstAsync();
            //if (shelfInfo == null)
            //{
            //    return new ResponseCommon<List<string>>()
            //    {
            //        Code = 201,
            //        Message = $"导入失败:当前工位不存在货架，请呼叫货架后再进行操作！",
            //        Data = null,
            //    };
            //}
            //货架编码校验
            var shelfCodes = lists.Select(t => t.货架编码).Distinct().ToList();

            var shelfInfosInDb = await DbHelp.db.Queryable<ShelfInfo>()
                                           .Where(t => shelfCodes.Contains(t.ShelfCode))
                                           .Where(t => t.IsEnable)
                                           .ToListAsync();
            if (shelfInfosInDb == null)
            {
                return new ResponseCommon<List<string>>()
                {
                    Code = 201,
                    Message = $"导入失败:货架编码无效！请重试！",
                    Data = null,
                };
            }
            //判断如果导入表中的货架编码数量与数据库中有效的货架数量不一致证明中间有无效的货架编码
            if (shelfInfosInDb != null && shelfInfosInDb.Count < shelfCodes.Count)
            {
                var shelfCodesInDb = shelfInfosInDb.Select(t => t.ShelfCode).ToList();
                shelfCodes.RemoveAll(t => shelfCodesInDb.Contains(t));
                if (shelfCodes.Count > 0)
                {
                    return new ResponseCommon<List<string>>()
                    {
                        Code = 201,
                        Message = $"导入失败:以下货架编码无效!\r\n{string.Join(",", shelfCodes)}",
                        Data = null,
                    };
                }
            }

            //单据类型校验 物料类型数量较小 不会对内存造成负担
            var orderTypesInDb = await DbHelp.db.Queryable<OrderTypeInfo>()
                                                .ToListAsync();
            var orderTypeNamesInDb = orderTypesInDb.Select(t => t.OrderTypeName)
                                                   .ToList();
            //数量、物料编码等必填项的校验
            foreach (var matDetailCurrentInfo in lists)
            {
                if (matDetailCurrentInfo.数量 == null || matDetailCurrentInfo.数量 <= 0)
                {
                    return new ResponseCommon<List<string>>()
                    {
                        Code = 201,
                        Message = $"导入失败:数量应该大于0!",
                        Data = null,
                    };
                }
                if (string.IsNullOrEmpty(matDetailCurrentInfo.物料编码))
                {
                    return new ResponseCommon<List<string>>()
                    {
                        Code = 201,
                        Message = $"导入失败:物料编码必填!",
                        Data = null,
                    };
                }
                if (!string.IsNullOrEmpty(matDetailCurrentInfo.单据类型) && !orderTypeNamesInDb.Contains(matDetailCurrentInfo.单据类型))
                {
                    return new ResponseCommon<List<string>>()
                    {
                        Code = 201,
                        Message = $"导入失败:单据类型[{matDetailCurrentInfo.单据类型}]无效!",
                        Data = null,
                    };
                }

                //不校验货架
                //if (!string.IsNullOrEmpty(matDetailCurrentInfo.货架编码) && matDetailCurrentInfo.货架编码 == shelfInfo.ShelfCode)
                //{
                //    return new ResponseCommon<List<string>>()
                //    {
                //        Code = 201,
                //        Message = $"导入失败:货架[{matDetailCurrentInfo.货架编码}]不是当前工位的货架!",
                //        Data = null,
                //    };
                //}
            }

            #region 物料编码校验
            //物料编码校验  物料编码的数据可能比较多 所以有可能会对服务器内存造成负担所以采用以下形式进行校验
            var matCodes = lists.Select(t => t.物料编码)
                                .Distinct()
                                .ToList();

            var matBaseInfoInDb = await DbHelp.db.Queryable<MatBaseInfo>()
                                        .Where(t => matCodes.Contains(t.MatCode))
                                        .Where(t => t.IsEnable == true)
                                        .ToListAsync();
            if (matBaseInfoInDb == null)
            {
                return new ResponseCommon<List<string>>()
                {
                    Code = 201,
                    Message = $"导入失败:请重试！",
                    Data = null,
                };
            }
            //判断如果导入表中的物料编码数量与数据库中有效的编码数量不一致证明中间有无效的物料编码
            if (matBaseInfoInDb != null && matBaseInfoInDb?.Count < matCodes.Count)
            {
                var matCodesInDb = matBaseInfoInDb.Select(t => t.MatName).ToList();
                matCodes.RemoveAll(t => matCodesInDb.Contains(t));
                if (matCodes.Count > 0)
                {
                    return new ResponseCommon<List<string>>()
                    {
                        Code = 201,
                        Message = $"导入失败:以下物料编码无效!\r\n{string.Join(",", matCodes)}",
                        Data = null,
                    };
                }
            }
            #endregion

            #endregion

            #region 导入数据
            try
            {
                await DbHelp.db.BeginTranAsync();
                foreach (var info in lists)
                {
                    var matBaseInfo = matBaseInfoInDb?.Where(t => t.MatCode == info.物料编码).First();
                    var shelfInfo = shelfInfosInDb?.Where(t => t.ShelfCode == info.货架编码).First();
                    var orderType = orderTypesInDb?.Where(t => t.OrderTypeName == info.单据类型).FirstOrDefault();
                    //应该是不能走进的分支
                    if (matBaseInfo == null || shelfInfo == null)
                    {
                        continue;
                    }
                    var matDetailCurrentInfo = new MatDetailCurrentInfo()
                    {

                        ShelfId = shelfInfo.Id,
                        ShelfCode = shelfInfo.ShelfCode,
                        ShelfType = shelfInfo.ShelfTypeName,

                        MatCode = matBaseInfo.MatCode,
                        MatName = matBaseInfo.MatName,
                        MatBatch = info.物料批次,
                        MatSpec = matBaseInfo.MatSpec,
                        MatUnit = matBaseInfo.MatUnit,
                        MatSupplier = matBaseInfo.MatSupplier,
                        MatCustomer = matBaseInfo.MatCustomer,
                        MatQty = info.数量.GetValueOrDefault(),

                        OrderTypeId = orderType?.Id,
                        OrderTypeName = orderType?.OrderTypeName,
                        OrderNumber = info.单据编号,
                        StationCode = stationCode,

                        ModifyUser = userName,

                    };
                    await DbHelp.db.Insertable(matDetailCurrentInfo).ExecuteCommandAsync();

                    var historyInfo = new MatDetailHistoryInfo()
                    {
                        ShlefId = matDetailCurrentInfo.ShelfId,
                        ShelfType = matDetailCurrentInfo.ShelfType,
                        ShelfCode = matDetailCurrentInfo.ShelfCode,

                        MatCode = matDetailCurrentInfo.MatCode,
                        MatName = matDetailCurrentInfo.MatName,
                        MatBatch = matDetailCurrentInfo.MatBatch,
                        MatSpec = matDetailCurrentInfo.MatSpec,
                        MatCustomer = matDetailCurrentInfo?.MatCustomer,
                        MatSupplier = matDetailCurrentInfo?.MatSupplier,

                        BeforeQty = 0,
                        AfterQty = matDetailCurrentInfo.MatQty,

                        ModifyTime = DateTime.Now,
                        ModifyUser = userName,
                        RecordType = RecordTypeEnum.新增,
                        FunctionType = FunctionTypeEnum.客户端物料绑定,
                    };
                    await DbHelp.db.Insertable(historyInfo).ExecuteCommandAsync();

                }
                await DbHelp.db.CommitTranAsync();
                DataProcessManager.UpdateShelfStatus();
                return new ResponseCommon<List<string>>()
                {
                    Code = 200,
                    Message = "导入数据成功",
                    Data = null
                };
            }
            catch (Exception ex)
            {
                await DbHelp.db.RollbackTranAsync();
                var ErrList = new List<string>
                {
                    ex.Message
                };
                return new ResponseCommon<List<string>>()
                {
                    Code = 201,
                    Message = "导入失败",
                    Data = ErrList
                };
            }
            #endregion
        }
    }
}
