using Elasticsearch.Net;
using JiaZhiQuan.Common.ElasticSearch;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Senparc.Weixin.MP.Containers;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Dynamic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Wicture.DbRESTFul;
using Wicture.DbRESTFul.Cache;
using Wicture.DbRESTFul.Infrastructure.Repository;

namespace JiaZhiQuan.Common
{
    public static partial class RepositoryExtension
    {


        public async static Task<int> SyncStockBKMapping(this DbRESTFulRepository repository, IHttpClientFactory httpClientFactory)
        {
            // 获取所有版块列表
            var bkList = (await repository.QueryAsync<string>("select codeDisplay from n_resource where type=1")).ToList();
            var count = 0;
            if (bkList.Count > 0)
            {
                var pageSize = 50;
                var httpClient = httpClientFactory.CreateClient();
                var urlFormatter = "https://push2.eastmoney.com/api/qt/clist/get?pz=" + pageSize + "&pn={0:G}&fs=b:{1:G}&fields=f12";
                // 获取每个板块对应的股票信息
                foreach (var bk in bkList)
                {
                    var curIdx = 1;
                    List<string> stocks = new List<string>();
                    while (true)
                    {
                        var url = string.Format(urlFormatter, curIdx, bk);
                        var rst = await httpClient.GetStringAsync(url);
                        var loadComplete = false;
                        if (!string.IsNullOrEmpty(rst))
                        {
                            var data = JsonConvert.DeserializeObject<JObject>(rst)?.Value<JObject>("data");
                            if (data == null) break;
                            for (var i = 0; i < pageSize; i++)
                            {
                                var code = data.Value<JObject>("diff")?.Value<JObject>(i.ToString())?.Value<string>("f12");
                                if (string.IsNullOrEmpty(code))
                                {
                                    loadComplete = true;
                                    break;
                                }
                                stocks.Add(code);
                            }
                        }
                        if (loadComplete) break;
                        curIdx++;
                    }
                    // 更新关系到数据库中
                    var bkCode = "1_" + bk;
                    var stockCodes = stocks.Select(e => "1_" + e);
                    if (stockCodes.Count() > 0)
                    {
                        await repository.QueryAsync<dynamic>($"insert ignore into n_resource_stock_bk_map(stockCode, bkCode) values(@stockCode, '{bkCode}')", stockCodes.Select(e => new { stockCode = e }), null, null, false);
                        await repository.QueryAsync<dynamic>("delete from n_resource_stock_bk_map where bkCode=@bkCode and stockCode not in @stockCodes", new { bkCode, stockCodes }, null, null, false);
                    }
                    else
                    {
                        await repository.QueryAsync<dynamic>("delete from n_resource_stock_bk_map where bkCode=@bkCode", new { bkCode }, null, null, false);
                    }
                    count += stocks.Count;
                }
            }
            return count;
        }

        public async static Task<int> SyncStock(this DbRESTFulRepository repository, int marketType, IHttpClientFactory httpClientFactory)
        {
            var count = 0;
            var pageSize = 2000;
            var pageIndex = 1;
            var httpClient = httpClientFactory.CreateClient();
            var fsList = new List<KeyValuePair<int, string>>();
            if (marketType == 0 || marketType == 1) fsList.Add(new KeyValuePair<int, string>(1, "m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048"));
            if (marketType == 0 || marketType == 2) fsList.Add(new KeyValuePair<int, string>(2, "m:128+t:3,m:128+t:4,m:128+t:1,m:128+t:2"));
            if (marketType == 0 || marketType == 4) fsList.Add(new KeyValuePair<int, string>(4, "m:105,m:106,m:107"));
            
            foreach (var task in fsList)
            {
                var fs = task.Value;
                marketType = task.Key;
                var urlFormatter = "http://22.push2.eastmoney.com/api/qt/clist/get?pn={0:G}&pz=" + pageSize + "&fid=f12&fs=" + fs + "&fields=f12,f14";
                var loadComplete = false;
                while (true)
                {
                    var stocks = new List<JObject>();
                    var url = string.Format(urlFormatter, pageIndex);
                    var rst = await httpClient.GetStringAsync(url);
                    if (!string.IsNullOrEmpty(rst))
                    {
                        var data = JsonConvert.DeserializeObject<JObject>(rst)?.Value<JObject>("data");
                        if (data == null) break;
                        for (var i = 0; i < pageSize; i++)
                        {
                            var item = data.Value<JObject>("diff")?.Value<JObject>(i.ToString());
                            if (item == null)
                            {
                                loadComplete = true;
                                break;
                            }
                            stocks.Add(item);
                        }
                    }

                    if (stocks.Count > 0)
                    {
                        await repository.QueryAsync<dynamic>("insert into n_resource(`code`, codeDisplay, name, type, marketType) values(@code, @codeDisplay, @name, 0, " + marketType + ") ON DUPLICATE KEY update name=@name;", stocks.Select(e => new { code = marketType + "_" + e.Value<string>("f12"), codeDisplay = e.Value<string>("f12"), name = e.Value<string>("f14") }), null, null, false);
                    }

                    count += stocks.Count;
                    if (loadComplete) break;
                    pageIndex++;
                }
            }
            return count;
        }

    }

}
