using BBWY.Common.Http;
using BBWY.Common.Models;
using BBWY.Server.Model;
using BBWY.Server.Model.Db;
using BBWY.Server.Model.Dto;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Yitter.IdGenerator;

namespace BBWY.Server.Business
{
    public class JDStockNumWarningBusiness : BaseSyncBusiness, IDenpendency
    {
        private IList<Enums.StorageType> validStorageTypeList;
        private DingDingBusiness dingDingBusiness;

        public JDStockNumWarningBusiness(RestApiService restApiService, IOptions<GlobalConfig> options, NLogManager nLogManager, IFreeSql fsql, IIdGenerator idGenerator, TaskSchedulerManager taskSchedulerManager, VenderBusiness venderBusiness, YunDingBusiness yunDingBusiness, DingDingBusiness dingDingBusiness) : base(restApiService, options, nLogManager, fsql, idGenerator, taskSchedulerManager, venderBusiness, yunDingBusiness)
        {
            validStorageTypeList = new List<Enums.StorageType>() {
                Enums.StorageType.云仓,
                Enums.StorageType.京仓,
                Enums.StorageType.本地自发
            };
            this.dingDingBusiness = dingDingBusiness;
        }

        public void StartCheckStockNum()
        {
            var storeHouseList = fsql.Select<Storehouse>().Where(s => s.Platform == Enums.Platform.京东).ToList();
            var shopList = venderBusiness.GetShopList(platform: Enums.Platform.京东, filterTurnoverDays: true);
            foreach (var shop in shopList)
            {
                Task.Factory.StartNew(() => CheckStockNum(shop, storeHouseList), CancellationToken.None, TaskCreationOptions.LongRunning, taskSchedulerManager.StockNumWarningTaskScheduler);
            }
        }

        private void CheckStockNum(ShopResponse shop, IList<Storehouse> storeHouseList)
        {
            var loggerName = $"库存预警-{shop.ShopName}";
            try
            {
                long shopId = long.Parse(shop.ShopId);
                var yesterDayDate = DateTime.Now.Date.AddDays(-1);
                var ysterDayTime = DateTime.Now.Date.AddSeconds(-1);

                //查询符合条件的sku (昨日 && 非赠品 && 销量>取消 && 非代发和刷单)
                var yesterDaySkuIds = fsql.Select<SkuDailySalesDetail, OrderSku, Order>()
                                          .InnerJoin((s, osku, o) => s.Sku == osku.SkuId)
                                          .InnerJoin((s, osku, o) => osku.OrderId == o.Id)
                                          .Where((s, osku, o) => s.ShopId == shopId &&
                                                                 s.Date == yesterDayDate &&
                                                                 s.IsGift == false &&
                                                                 s.ItemTotal > s.CancelItemTotal &&
                                                                 o.StartTime >= yesterDayDate &&
                                                                 o.StartTime <= ysterDayTime &&
                                                                 validStorageTypeList.Contains(o.StorageType.Value))
                                          .Distinct()
                                          .ToList((s, osku, o) => s.Sku);

                //查询近15天的销量(5个周期)
                var allCycleStartDate = yesterDayDate.AddDays(-14);
                var skuSaleDailyList = fsql.Select<SkuDailySalesDetail>()
                                           .Where(s => s.Date >= allCycleStartDate && s.Date <= yesterDayDate)
                                           .Where(s => yesterDaySkuIds.Contains(s.Sku))
                                           .ToList();

                var firstCycleStartDate = yesterDayDate.AddDays(-8);
                var firstCycleEndDate = firstCycleStartDate.AddDays(2);

                var secondCycleStartDate = firstCycleEndDate.AddDays(1);
                var secondCycleEndDate = secondCycleStartDate.AddDays(2);

                var thirdCycleStartDate = secondCycleEndDate.AddDays(1);
                var thirdCycleEndDate = thirdCycleStartDate.AddDays(2);

                var _7dAvgStartDate = DateTime.Now.Date.AddDays(-7);

                bool isSendDingTalk = false;
                var dingdingContentBuilder = new StringBuilder();
                dingdingContentBuilder.Append(shop.ShopName);
                dingdingContentBuilder.AppendLine();

                foreach (var sku in yesterDaySkuIds)
                {
                    //第一周期销量
                    var firstCycleSaleList = skuSaleDailyList.Where(s => s.Sku == sku && s.Date >= firstCycleStartDate && s.Date <= firstCycleEndDate);
                    var firstCycleItemTotal = firstCycleSaleList.Count() > 0 ? firstCycleSaleList.Sum(s => s.ItemTotal - s.CancelItemTotal) : 0;
                    if (firstCycleItemTotal < 0)
                        firstCycleItemTotal = 0;

                    //第二周期销量
                    var secondCycleSaleList = skuSaleDailyList.Where(s => s.Sku == sku && s.Date >= secondCycleStartDate && s.Date <= secondCycleEndDate);
                    var secondCycleItemTotal = secondCycleSaleList.Count() > 0 ? secondCycleSaleList.Sum(s => s.ItemTotal - s.CancelItemTotal) : 0;
                    if (secondCycleItemTotal < 0)
                        secondCycleItemTotal = 0;

                    //第三周期销量
                    var thirdCycleSaleList = skuSaleDailyList.Where(s => s.Sku == sku && s.Date >= thirdCycleStartDate && s.Date <= thirdCycleEndDate);
                    var thirdCycleItemTotal = thirdCycleSaleList.Count() > 0 ? thirdCycleSaleList.Sum(s => s.ItemTotal - s.CancelItemTotal) : 0;
                    if (thirdCycleItemTotal < 0)
                        thirdCycleItemTotal = 0;

                    //计算周期增幅
                    var _2Ratio = firstCycleItemTotal == 0 ? 0 : 1.0 * secondCycleItemTotal / firstCycleItemTotal - 1;
                    var _3Ratio = secondCycleItemTotal == 0 ? 0 : 1.0 * thirdCycleItemTotal / secondCycleItemTotal - 1;


                    var _7dSaleList = skuSaleDailyList.Where(s => s.Sku == sku && s.Date >= _7dAvgStartDate && s.Date <= yesterDayDate);
                    var _15dSaleList = skuSaleDailyList.Where(s => s.Sku == sku);
                    var _7dItemTotal = _7dSaleList.Sum(s => s.ItemTotal - s.CancelItemTotal);
                    if (_7dItemTotal < 0)
                        _7dItemTotal = 0;
                    var _15dItemTotal = _15dSaleList.Sum(s => s.ItemTotal - s.CancelItemTotal); //近15天销量
                    if (_15dItemTotal < 0)
                        _15dItemTotal = 0;
                    var _7dAvgItemTotal = 1.0 * _7dItemTotal / 7; //近7天日均销量


                    Enums.SkuStockNumCycleType skuStockNumCycleType = Enums.SkuStockNumCycleType.暂无周期;
                    if (_2Ratio >= 0.2 && _3Ratio >= 0.2)
                        skuStockNumCycleType = Enums.SkuStockNumCycleType.增长期;
                    else if (_2Ratio >= -0.2 && _2Ratio <= 0.2 && _3Ratio >= -0.2 && _3Ratio <= 0.2)
                        skuStockNumCycleType = Enums.SkuStockNumCycleType.稳定期;
                    else if (_2Ratio < -0.2 && _3Ratio < -0.2)
                        skuStockNumCycleType = Enums.SkuStockNumCycleType.衰退期;

                    var logContentBuilder = new StringBuilder();
                    logContentBuilder.AppendLine($"SKU:{sku}");
                    logContentBuilder.AppendLine($"商品状态:{skuStockNumCycleType}");
                    logContentBuilder.AppendLine($"第一周销量:{firstCycleItemTotal}");
                    logContentBuilder.AppendLine($"第二周期销量:{secondCycleItemTotal}, 相比第一周幅度:{_2Ratio * 100}%");
                    logContentBuilder.AppendLine($"第三周期销量:{thirdCycleItemTotal}, 相比第二周幅度:{_3Ratio * 100}%");
                    logContentBuilder.AppendLine($"近7天销量:{_7dItemTotal}");
                    logContentBuilder.AppendLine($"近15天销量:{_15dItemTotal}");
                    logContentBuilder.AppendLine($"7天日均销量:{_7dAvgItemTotal}");

                    //dingdingContentBuilder.Append($"SKU:{sku}\n");
                    //dingdingContentBuilder.Append($"商品状态:{skuStockNumCycleType}\n");
                    //dingdingContentBuilder.Append($"近7天销量:{_7dItemTotal}\n");
                    //dingdingContentBuilder.Append($"7天日均销量:{_7dItemTotal}\n");


                    if (skuStockNumCycleType == Enums.SkuStockNumCycleType.暂无周期)
                    {
                        nLogManager.GetLogger(loggerName).Info(logContentBuilder);
                        continue;
                    }

                    Thread.Sleep(1000);
                    var restApiResult = restApiService.SendRequest(GetPlatformRelayAPIHost(shop.PlatformId), "api/platformsdk/GetStockNumBySku", new SearchProductSkuRequest()
                    {
                        AppKey = shop.AppKey,
                        AppSecret = shop.AppSecret,
                        AppToken = shop.AppToken,
                        Platform = shop.PlatformId,
                        Sku = sku
                    }, GetYunDingRequestHeader(), HttpMethod.Post);
                    if (restApiResult.StatusCode != System.Net.HttpStatusCode.OK)
                        throw new Exception($"{sku} {restApiResult.Content}");
                    var response = JsonConvert.DeserializeObject<ApiResponse<JArray>>(restApiResult.Content);
                    if (response.Data == null || response.Data.Count() == 0)
                    {
                        logContentBuilder.AppendLine("未查询到JD库存数据");
                        nLogManager.GetLogger(loggerName).Info(logContentBuilder);
                        continue;
                    }

                    var skuStockNumList = response.Data.Select(j => new
                    {
                        StockNum = j.Value<int>("stockNum"),
                        Store = storeHouseList.FirstOrDefault(s => s.Id == j.Value<string>("storeId")),
                        StoreId = j.Value<string>("storeId"),
                        SkuId = sku
                    });

                    var skuStockNumGroups = skuStockNumList.GroupBy(s => s.Store?.Type ?? Enums.StockType.商家仓);  //按仓库类型算库存
                    foreach (var skuStockNumGroup in skuStockNumGroups)
                    {
                        var totalStockNum = skuStockNumGroup.Sum(s => s.StockNum);  //总库存
                        var lessDay = _7dAvgItemTotal == 0 ? 0 : totalStockNum / _7dAvgItemTotal; //剩余天数
                        bool isWarning = false;  //是否触发提醒
                        int suggestStockNum = 0; //建议备货量
                        if (skuStockNumCycleType == Enums.SkuStockNumCycleType.增长期)
                        {
                            if (lessDay < 15)
                            {
                                isWarning = true;
                                if (_15dItemTotal <= 2)
                                    suggestStockNum = 0;
                                else if (shop.SkuSafeTurnoverDays == 28)
                                    suggestStockNum = (int)Math.Ceiling(_7dItemTotal * 4 * 1.5);
                                else if (shop.SkuSafeTurnoverDays == 21)
                                    suggestStockNum = (int)Math.Ceiling(_7dItemTotal * 3 * 1.5);
                                else if (shop.SkuSafeTurnoverDays == 14)
                                    suggestStockNum = (int)Math.Ceiling(_7dItemTotal * 2 * 1.5);
                            }
                        }
                        else if (skuStockNumCycleType == Enums.SkuStockNumCycleType.稳定期)
                        {
                            if (lessDay < 8)
                            {
                                isWarning = true;
                                if (_15dItemTotal <= 2)
                                    suggestStockNum = 0;
                                else if (shop.SkuSafeTurnoverDays == 28)
                                    suggestStockNum = _7dItemTotal * 4;
                                else if (shop.SkuSafeTurnoverDays == 21)
                                    suggestStockNum = _7dItemTotal * 3;
                                else if (shop.SkuSafeTurnoverDays == 14)
                                    suggestStockNum = _7dItemTotal * 2;
                            }
                        }
                        else if (skuStockNumCycleType == Enums.SkuStockNumCycleType.衰退期)
                        {
                            if (lessDay < 8)
                            {
                                isWarning = true;
                                suggestStockNum = 0;
                            }
                        }

                        if (isWarning)
                        {
                            isSendDingTalk = true;

                            dingdingContentBuilder.Append($"SKU:{sku}\n");
                            dingdingContentBuilder.Append($"商品状态:{skuStockNumCycleType}\n");
                            dingdingContentBuilder.Append($"近7天销量:{_7dItemTotal}\n");
                            dingdingContentBuilder.Append($"近15天销量:{_15dItemTotal}\n");
                            foreach (var stockNumInfo in skuStockNumGroup)
                                dingdingContentBuilder.Append($"{stockNumInfo.Store?.Name ?? stockNumInfo.StoreId}:{stockNumInfo.StockNum}件\n");
                            if (skuStockNumCycleType == Enums.SkuStockNumCycleType.增长期 || skuStockNumCycleType == Enums.SkuStockNumCycleType.稳定期)
                            {
                                if (suggestStockNum != 0)
                                    dingdingContentBuilder.Append($"{skuStockNumGroup.Key}库存低于安全周转天数,建议备货{suggestStockNum}件");
                                else
                                    dingdingContentBuilder.Append($"建议暂停备货,采购代发");
                            }
                            else if (skuStockNumCycleType == Enums.SkuStockNumCycleType.衰退期)
                                dingdingContentBuilder.Append($"{skuStockNumGroup.Key}库存商品进入衰退期,建议暂停备货,采购代发");
                            dingdingContentBuilder.AppendLine();
                        }

                        #region 拼接sku在当前类型仓库的日志
                        logContentBuilder.AppendLine($"仓库类型:{skuStockNumGroup.Key}");
                        logContentBuilder.AppendLine($"总库存:{totalStockNum}");
                        logContentBuilder.AppendLine($"剩余天数:{lessDay}");
                        logContentBuilder.AppendLine($"建议备货量:{suggestStockNum}");
                        logContentBuilder.AppendLine($"是否触发预警:{isWarning}");
                        #endregion
                    }
                    nLogManager.GetLogger(loggerName).Info(logContentBuilder);
                }

                if (isSendDingTalk)
                {
                    dingDingBusiness.SendDingDingBotMessage(shop.DingDingKey, shop.DingDingWebHook, dingdingContentBuilder.ToString());
                    //var secret = shop.DingDingKey;
                    //var timestamp = DateTime.Now.DateTimeToStamp();
                    //var stringToSign = timestamp + "\n" + secret;
                    //var sign = EncryptWithSHA256(stringToSign, secret);
                    //var url = $"{shop.DingDingWebHook}&timestamp={timestamp}&sign={sign}";
                    //var result = restApiService.SendRequest(url, string.Empty, new
                    //{
                    //    msgtype = "text",
                    //    text = new
                    //    {
                    //        content = dingdingContentBuilder.ToString()
                    //    }
                    //}, null, HttpMethod.Post);
                    //if (result.StatusCode != System.Net.HttpStatusCode.OK)
                    //    throw new Exception($"{shop.ShopName} 发送钉钉库存预警失败 {result.Content}");
                }
            }
            catch (Exception ex)
            {
                nLogManager.GetLogger(loggerName).Error(ex, "查询sku库存失败");
            }
        }
    }
}