using System.Threading.Tasks;
using System;
using Wicture.DbRESTFul.Infrastructure.Repository;
using System.Linq;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Net.Http;
using JiaZhiQuan.Common.Utils;
using Wicture.DbRESTFul.Cache;
using Newtonsoft.Json;
using Polly;
using Wicture.DbRESTFul.Rpc.Client;

namespace JiaZhiQuan.Common
{
    public static partial class RepositoryExtension
    {

        /// <summary>
        /// 获取至少前7个交易日(不考虑停牌)
        /// </summary>
        public static async Task<List<string>> GetQTRecentTradeDaysBefore7(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, string dateStr)
        {
            var key = CacheKeys.QTRecentTradeDaysBefore7(dateStr);
            var tradeDates = await cacheProvider.Get<List<string>>(key);
            if (tradeDates == null || tradeDates.Count == 0)
            {
                tradeDates = (await repository.QueryAsync<DateTime>(
                    $"select `date` from n_stock_trade_date where `date`<='{dateStr}' order by `date` desc limit 7"))
                    .Select(e => e.ToString("yyyy-MM-dd")).ToList();
                await cacheProvider.Set(key, tradeDates, CacheKeys.QTRecentTradeDaysCacheSecs);
            }
            return tradeDates;
        }

        /// <summary>
        /// 获取当日最近前后3个交易日(不考虑停牌)
        /// </summary>
        public static async Task<List<string>> GetQTTradeDaysAround3Days(this DbRESTFulRepository repository,
            string dateStr, RedisCacheProvider cacheProvider)
        {
            // 获取当日最近前后3个交易日
            var key = CacheKeys.QTRecentTradeDaysRound3(dateStr);
            var tradeDates = await cacheProvider.Get<List<string>>(key);
            if (tradeDates == null || tradeDates.Count == 0)
            {
                var tradeDatesBefore = (await repository.QueryAsync<DateTime>(
                    $"select `date` from n_stock_trade_date where `date`<='{dateStr}' order by `date` desc limit 4")).ToList();
                var tradeDatesAfter = (await repository.QueryAsync<DateTime>(
                    $"select `date` from n_stock_trade_date where `date`>='{dateStr}' order by `date` asc limit 4")).ToList();
                tradeDates = tradeDatesBefore.Concat(tradeDatesAfter).Distinct().OrderBy(e => e)
                    .Select(e => e.ToString("yyyy-MM-dd")).ToList();
                await cacheProvider.Set(key, tradeDates, CacheKeys.QTRecentTradeDaysCacheSecs);
            }

            return tradeDates;
        }

        /// <summary>
        /// 获取某日对应的停牌信息（通过AKShare获取）
        /// </summary>
        public static async Task<List<QTSuspensionData>> GetQTSuspensionDataList(this DbRESTFulRepository repository,
            string dateStr, RedisCacheProvider cacheProvider, IHttpClientFactory clientFactory)
        {
            var key = CacheKeys.QTSuspensionDataList(dateStr);
            var list = await cacheProvider.Get<List<QTSuspensionData>>(key);
            if (list == null)
            {
                list = await QTUtils.GetAKSData<List<QTSuspensionData>>(clientFactory, "stock_tfp_em",
                                new { date = dateStr.Replace("-", "") });
                await cacheProvider.Set(key, list, CacheKeys.QTSuspensionDataListCacheSecs);
            }

            return list;
        }

        /// <summary>
        /// 判断某一个合约在某一个交易日是否停牌
        /// </summary>
        public static bool QTIsSuspended(this DbRESTFulRepository repository, string contractCode, DateTime tradeDate, List<QTSuspensionData> suspensions)
        {
            var isIndex = (contractCode.Contains("SH") && !contractCode.StartsWith("6")) ||
                          (contractCode.Contains("SZ") && !contractCode.StartsWith("0"));
            if (isIndex) return false;
            var codePart = contractCode.Split('.', StringSplitOptions.RemoveEmptyEntries)[0];
            return suspensions.Any(e =>
                codePart.Equals(e.代码) && e.停牌时间 != null &&
                e.停牌时间.Value.Date <= tradeDate.Date &&
                (e.停牌截止时间 == null || e.停牌截止时间 >= tradeDate.Date) &&
                !(e.停牌期限 ?? string.Empty).Contains("盘中"));
        }
    }
}
