/***********************************************************************
 *            Project: CoreCms
 *        ProjectName: 核心内容管理系统                                
 *                Web: https://www.corecms.net                      
 *             Author: 大灰灰                                          
 *              Email: jianweie@163.com                                
 *         CreateTime: 2021/1/31 21:45:10
 *        Description: 暂无
 ***********************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CoreCms.Net.Configuration;
using CoreCms.Net.IRepository;
using CoreCms.Net.IRepository.UnitOfWork;
using CoreCms.Net.IServices;
using CoreCms.Net.Loging;
using CoreCms.Net.Model.Entities;
using CoreCms.Net.Model.ViewModels.Api;
using CoreCms.Net.Model.ViewModels.UI;
using CoreCms.Net.Model.ViewModels.View;
using CoreCms.Net.Utility.Helper;
using Flurl.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;


namespace CoreCms.Net.Services
{
    /// <summary>
    /// 发货单表 接口实现
    /// </summary>
    public class CoreCmsBillDeliveryServices : BaseServices<CoreCmsBillDelivery>, ICoreCmsBillDeliveryServices
    {
        private readonly ICoreCmsBillDeliveryRepository _dal;
        private readonly ICoreCmsStoreServices _storeServices;
        private readonly ICoreCmsBillDeliveryItemServices _billDeliveryItemServices;
        private readonly ICoreCmsBillDeliveryOrderRelServices _billDeliveryOrderRelServices;
        private readonly ICoreCmsOrderLogServices _orderLogServices;
        private readonly ICoreCmsSettingServices _settingServices;
        private readonly IUnitOfWork _unitOfWork;
        private readonly IServiceProvider _serviceProvider;
        public CoreCmsBillDeliveryServices(
            IUnitOfWork unitOfWork,
            IServiceProvider serviceProvider
            , ICoreCmsBillDeliveryRepository dal
            , ICoreCmsStoreServices storeServices
            , ICoreCmsBillDeliveryItemServices billDeliveryItemServices
            , ICoreCmsBillDeliveryOrderRelServices billDeliveryOrderRelServices
            , ICoreCmsOrderLogServices orderLogServices
            , ICoreCmsSettingServices settingServices)
        {
            this._dal = dal;
            base.BaseDal = dal;
            _unitOfWork = unitOfWork;
            _serviceProvider = serviceProvider;
            _storeServices = storeServices;
            _billDeliveryItemServices = billDeliveryItemServices;
            _billDeliveryOrderRelServices = billDeliveryOrderRelServices;
            _orderLogServices = orderLogServices;
            _settingServices = settingServices;
        }


        /// <summary>
        /// 获取发货单列表
        /// </summary>
        /// <param name="orderId">订单编号</param>
        /// <returns></returns>
        public async Task<WebApiCallBack> GetDeliveryList(string orderId)
        {

            return await _dal.GetDeliveryList(orderId);
        }



        /// <summary>
        /// 批量发货，可以支持多个订单合并发货，单个订单拆分发货等。
        /// </summary>
        /// <param name="orderId">英文逗号分隔的订单号</param>
        /// <param name="logiCode">物流公司编码</param>
        /// <param name="logiNo">物流单号</param>
        /// <param name="items">发货明细</param>
        /// <param name="storeId">店铺收货地址</param>
        /// <param name="shipName">收货人姓名</param>
        /// <param name="shipMobile">收货人电话</param>
        /// <param name="shipAreaId">省市区id</param>
        /// <param name="shipAddress">收货地址</param>
        /// <param name="memo">发货描述</param>
        /// <returns></returns>
        public async Task<WebApiCallBack> BatchShip(string[] orderId, string logiCode, string logiNo, Dictionary<int, int> items, int storeId = 0, string shipName = "", string shipMobile = "", int shipAreaId = 0, string shipAddress = "", string memo = "")
        {
            using var container = _serviceProvider.CreateScope();
            var jm = new WebApiCallBack();

            var orderService = container.ServiceProvider.GetService<ICoreCmsOrderServices>();
            //获取订单详情
            var dInfoResult = await orderService.GetOrderShipInfo(orderId);
            if (!dInfoResult.status)
            {
                return dInfoResult;
            }
            var dInfo = dInfoResult.data as AdminOrderShipResult;
            var orders = dInfo.orders;

            //校验门店自提和普通订单收货地址是否填写
            if (storeId != 0)
            {
                var storeModel = await _storeServices.QueryByIdAsync(storeId);
                if (storeModel == null)
                {
                    jm.msg = GlobalErrorCodeVars.Code10000;
                    jm.data = 1000;
                    jm.code = 1000;
                    return jm;
                }
                shipName = storeModel.storeName;
                shipMobile = storeModel.mobile;
                shipAreaId = storeModel.areaId;
                shipAddress = storeModel.address;
            }
            if (string.IsNullOrEmpty(shipName) || string.IsNullOrEmpty(shipMobile) || string.IsNullOrEmpty(shipAddress) || shipAreaId == 0)
            {
                jm.msg = "收货地址信息不全";
                jm.otherData = new
                {
                    shipName,
                    shipMobile,
                    shipAddress,
                    shipAreaId
                };
                return jm;
            }
            var billDelivery = new CoreCmsBillDelivery();
            billDelivery.orderId = string.Join(",", orderId);
            billDelivery.deliveryId = CommonHelper.GetSerialNumberType((int)GlobalEnumVars.SerialNumberType.发货单编号);
            billDelivery.logiCode = logiCode;
            billDelivery.logiNo = logiNo;
            billDelivery.shipAreaId = shipAreaId;
            billDelivery.shipAddress = shipAddress;
            billDelivery.shipName = shipName;
            billDelivery.shipMobile = shipMobile;
            billDelivery.status = (int)GlobalEnumVars.BillDeliveryStatus.Already;
            billDelivery.memo = memo;
            billDelivery.createTime = DateTime.Now;

            //设置发货明细
            var bdRel = new List<CoreCmsBillDeliveryItem>();

            //校验发货内容
            var tNum = 0;
            foreach (var item in items)
            {
                var orderItem = dInfo.items.Find(p => p.productId == item.Key);
                if (orderItem == null)
                {
                    //发货的商品不在发货明细里，肯定有问题
                    jm.msg = GlobalErrorCodeVars.Code10000;
                    return jm;
                }
                //判断总发货数量
                tNum = tNum + item.Value;

                if ((orderItem.nums - orderItem.sendNums - (orderItem.reshipNums - orderItem.reshipedNums)) < item.Value)
                {
                    jm.msg = orderItem.name + "发超了";
                    return jm;
                }

                //构建发货单明细
                dInfo.items.ForEach(p =>
                {
                    var bdItem = new CoreCmsBillDeliveryItem();
                    bdItem.deliveryId = billDelivery.deliveryId;
                    bdItem.productId = p.productId;
                    bdItem.goodsId = p.goodsId;
                    bdItem.bn = p.bn;
                    bdItem.sn = p.sn;
                    bdItem.weight = p.weight;
                    bdItem.name = p.name;
                    bdItem.addon = !string.IsNullOrEmpty(p.addon) ? p.addon : "";
                    bdItem.nums = orderItem.nums;
                    bdRel.Add(bdItem);
                });
            }
            if (tNum < 1)
            {
                jm.msg = "请至少发生一件商品!";
                return jm;
            }
            //事务处理开始


            //插入发货单主体表
            await base.InsertAsync(billDelivery);

            //插入发货单明细表
            await _billDeliveryItemServices.InsertAsync(bdRel);

            //订单更新发货状态，发送各种消息
            var rels = new List<CoreCmsBillDeliveryOrderRel>(); //关系表
            foreach (var order in orders)
            {
                await orderShip(order, items, billDelivery, storeId);
                var rel = new CoreCmsBillDeliveryOrderRel
                {
                    deliveryId = billDelivery.deliveryId,
                    orderId = order.orderId
                };
                rels.Add(rel);
            }
            if (rels.Any())
            {
                await _billDeliveryOrderRelServices.InsertAsync(rels);
            }
            jm.status = true;
            jm.msg = "发货成功";


            return jm;
        }


        /// <summary>
        /// 给订单发货
        /// </summary>
        /// <param name="orderInfo">订单信息</param>
        /// <param name="items">总的发货包裹内容</param>
        /// <param name="deliveryInfo">发货单信息</param>
        /// <param name="storeId">门店自提还是普通订单，0是普通订单，其他是门店自提</param>
        private async Task<bool> orderShip(CoreCmsOrder orderInfo, Dictionary<int, int> items, CoreCmsBillDelivery deliveryInfo, int storeId = 0)
        {
            using var container = _serviceProvider.CreateScope();
            var orderService = container.ServiceProvider.GetService<ICoreCmsOrderServices>();
            var billLadingService = container.ServiceProvider.GetService<ICoreCmsBillLadingServices>();
            var messageCenterServices = container.ServiceProvider.GetService<ICoreCmsMessageCenterServices>();
            var logisticsServices = container.ServiceProvider.GetService<ICoreCmsLogisticsServices>();
            var stockLogServices = container.ServiceProvider.GetService<ICoreCmsStockLogServices>();
            var stockServices = container.ServiceProvider.GetService<ICoreCmsStockServices>();

            var stockLogs = new List<CoreCmsStockLog>();

            var itemList = new Dictionary<int, int>();
            foreach (var item in orderInfo.items)
            {
                if (items.ContainsKey(item.productId))
                {
                    var maxNum = item.nums - item.reshipNums - item.sendNums;
                    if (maxNum > 0) //如果此条订单明细需要发货的话
                    {
                        var sendNum = maxNum;
                        if (items[item.productId] > maxNum)
                        {
                            //足够发此条记录的话
                            itemList.Add(item.productId, maxNum);
                            items[item.productId] = items[item.productId] - maxNum;
                        }
                        else
                        {
                            //此条订单都发不满的情况下
                            itemList.Add(item.productId, items[item.productId]);
                            sendNum = items[item.productId];
                        }

                        var sLog = new CoreCmsStockLog
                        {
                            stockId = deliveryInfo.deliveryId,
                            productId = item.id,
                            goodsId = item.goodsId,
                            nums = -sendNum,
                            sn = item.sn,
                            bn = item.bn,
                            goodsName = item.name,
                            spesDesc = item.addon
                        };
                        stockLogs.Add(sLog);
                    }
                }
            }
            //如果有发货信息，就去给订单更新发货状态
            if (itemList.Keys.Count <= 0)
            {
                return false;
            }
            var res = await orderService.EditShipStatus(orderInfo.orderId, itemList);

            //如果是门店自提，生成提货单
            if (storeId != 0)
            {
                await billLadingService.AddData(orderInfo.orderId, storeId, orderInfo.shipName, orderInfo.shipMobile);
            }

            if (res.status == true)
            {
                //添加操作日志
                var log = new CoreCmsOrderLog();
                log.orderId = orderInfo.orderId;
                log.userId = orderInfo.userId;
                log.type = (int)GlobalEnumVars.OrderLogTypes.LOG_TYPE_SHIP;
                log.msg = "订单发货操作，发货单号：" + deliveryInfo.deliveryId;
                log.data = JsonConvert.SerializeObject(deliveryInfo);
                log.createTime = DateTime.Now;
                await _orderLogServices.InsertAsync(log);

                var logistics = await logisticsServices.QueryByClauseAsync(p => p.logiCode == deliveryInfo.logiCode);
                deliveryInfo.logiName = logistics != null ? logistics.logiName : deliveryInfo.logiCode;
                //添加库存出库日志

                if (stockLogs.Any())
                {
                    var stock = new CoreCmsStock
                    {
                        manager = 0,
                        id = deliveryInfo.deliveryId,
                        createTime = DateTime.Now,
                        type = (int)GlobalEnumVars.StockType.DeliverGoods,
                        memo = log.msg
                    };
                    await stockServices.InsertAsync(stock);
                    await stockLogServices.InsertAsync(stockLogs);
                }

                //发送消息
                await messageCenterServices.SendMessage(orderInfo.userId, GlobalEnumVars.PlatformMessageTypes.DeliveryNotice.ToString(), JObject.FromObject(deliveryInfo));
            }
            return true;
        }


        /// <summary>
        /// 物流信息查询根据快递编码和单号查询(快递100)未使用
        /// </summary>
        /// <param name="code">查询的快递公司的编码， 一律用小写字母（如：yuantong）</param>
        /// <param name="no">查询的快递单号， 单号的最大长度是32个字符</param>
        /// <returns></returns>
        public async Task<WebApiCallBack> GetLogistic(string code, string no)
        {
            var jm = new WebApiCallBack();

            //快递100分配给贵司的的公司编号, 请在企业管理后台查看
            var allConfigs = await _settingServices.GetConfigDictionaries();
            var customer = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.Kuaidi100Customer);
            //签名， 用于验证身份， 按param + key + customer 的顺序进行MD5加密（注意加密后字符串一定要转大写）， 不需要加上“+”号， 如{“com”: “yuantong”, “num”: “500306190180”, “from”: “广东省深圳市”, “to”: “北京市朝阳区”}xxxxxxxxxxxxyyyyyyyyyyy yyyyyyyyyyyyyyyyyyyyy
            var key = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.Kuaidi100Key);

            if (string.IsNullOrEmpty(customer) || string.IsNullOrEmpty(key))
            {
                jm.msg = "快递查询接口公司编码及授权key获取失败";
            }

            var param = new KuaiDi100ApiPostParam();
            param.com = code.ToLowerInvariant();
            param.num = no;
            param.phone = "";
            param.from = "";
            param.to = "";
            param.resultv2 = 1;
            var jsonParamData = JsonConvert.SerializeObject(param);

            //签名加密
            var str = jsonParamData + key + customer;
            var signStr = CommonHelper.Md5For32(str).ToUpper();
            //实时查询请求地址
            var postUrl = "http://poll.kuaidi100.com/poll/query.do";

            var postData = new
            {
                customer,
                param = jsonParamData,
                sign = signStr
            };
            var result = await postUrl.WithHeader("Content-Type	", "application/x-www-form-urlencoded")
                                .PostJsonAsync(postData)
                                .ReceiveJson<KuaiDi100ApiPostResult>();
            if (result.status == "200")
            {
                jm.status = true;
                jm.data = result;
            }
            else
            {
                jm.status = false;
                jm.msg = !string.IsNullOrEmpty(result.message) ? result.message : "暂无消息";
            }

            return jm;
        }


        /// <summary>
        /// 发货单统计7天统计
        /// </summary>
        /// <returns></returns>
        public async Task<List<StatisticsOut>> Statistics()
        {
            return await _dal.Statistics();

        }

    }
}
