#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2024/2/20 17:00
Desc: 东方财富网-期货行情
https://qhweb.eastmoney.com/quote
"""

import re
from functools import lru_cache
from typing import Tuple, Dict

import pandas as pd
import requests


def __futures_hist_separate_char_and_numbers_em(symbol: str = "焦煤2506") -> tuple:
    """
    东方财富网-期货行情-交易所品种对照表原始数据
    https://quote.eastmoney.com/qihuo/al2505.html
    :param symbol: 股票代码
    :type symbol: str
    :return: 交易所品种对照表原始数据
    :rtype: pandas.DataFrame
    """
    char = re.findall(pattern="[\u4e00-\u9fa5a-zA-Z]+", string=symbol)
    numbers = re.findall(pattern=r"\d+", string=symbol)
    return char[0], numbers[0]


@lru_cache()
def __fetch_exchange_symbol_raw_em() -> list:
    """
    东方财富网-期货行情-交易所品种对照表原始数据
    https://quote.eastmoney.com/qihuo/al2505.html
    :return: 交易所品种对照表原始数据
    :rtype: pandas.DataFrame
    """
    url = "https://futsse-static.eastmoney.com/redis"
    params = {"msgid": "gnweb"}
    r = requests.get(url, params=params)
    data_json = r.json()
    all_exchange_symbol_list = []
    for item in data_json:
        params = {"msgid": str(item["mktid"])}
        r = requests.get(url, params=params)
        inner_data_json = r.json()
        for num in range(1, len(inner_data_json) + 1):
            params = {"msgid": str(item["mktid"]) + f"_{num}"}
            r = requests.get(url, params=params)
            inner_data_json = r.json()
            all_exchange_symbol_list.extend(inner_data_json)
    return all_exchange_symbol_list


@lru_cache()
def __get_exchange_symbol_map() -> Tuple[Dict, Dict, Dict, Dict]:
    """
    东方财富网-期货行情-交易所品种映射
    https://quote.eastmoney.com/qihuo/al2505.html
    :return: 交易所品种映射
    :rtype: pandas.DataFrame
    """
    all_exchange_symbol_list = __fetch_exchange_symbol_raw_em()
    c_contract_mkt = {}
    c_contract_to_e_contract = {}
    e_symbol_mkt = {}
    c_symbol_mkt = {}
    for item in all_exchange_symbol_list:
        c_contract_mkt[item["name"]] = item["mktid"]
        c_contract_to_e_contract[item["name"]] = item["code"]
        e_symbol_mkt[item["vcode"]] = item["mktid"]
        c_symbol_mkt[item["vname"]] = item["mktid"]
    return c_contract_mkt, c_contract_to_e_contract, e_symbol_mkt, c_symbol_mkt


def futures_hist_table_em() -> pd.DataFrame:
    """
    东方财富网-期货行情-交易所品种对照表
    https://quote.eastmoney.com/qihuo/al2505.html
    :return: 交易所品种对照表
    :rtype: pandas.DataFrame
    """
    all_exchange_symbol_list = __fetch_exchange_symbol_raw_em()
    temp_df = pd.DataFrame(all_exchange_symbol_list)
    temp_df = temp_df[["mktname", "name", "code"]]
    temp_df.columns = ["市场简称", "合约中文代码", "合约代码"]
    return temp_df


def futures_hist_em(
    symbol: str = "热卷主连",
    period: str = "daily",
    start_date: str = "19900101",
    end_date: str = "20500101",
) -> pd.DataFrame:
    """
    东方财富网-期货行情-行情数据
    https://qhweb.eastmoney.com/quote
    :param symbol: 期货代码
    :type symbol: str
    :param period: choice of {'daily', 'weekly', 'monthly'}
    :type period: str
    :param start_date: 开始日期
    :type start_date: str
    :param end_date: 结束日期
    :type end_date: str
    :return: 行情数据
    :rtype: pandas.DataFrame
    """
    url = "https://push2his.eastmoney.com/api/qt/stock/kline/get"
    period_dict = {"daily": "101", "weekly": "102", "monthly": "103"}
    c_contract_mkt, c_contract_to_e_contract, e_symbol_mkt, c_symbol_mkt = (
        __get_exchange_symbol_map()
    )
    try:
        sec_id = f"{c_contract_mkt[symbol]}.{c_contract_to_e_contract[symbol]}"
    except KeyError:
        symbol_char, numbers = __futures_hist_separate_char_and_numbers_em(symbol)
        if re.match(pattern="^[\u4e00-\u9fa5]+$", string=symbol_char):
            sec_id = str(c_symbol_mkt[symbol_char]) + "." + symbol
        else:
            sec_id = str(e_symbol_mkt[symbol_char]) + "." + symbol
    params = {
        "secid": sec_id,
        "klt": period_dict[period],
        "fqt": "1",
        "lmt": "10000",
        "end": "20500000",
        "iscca": "1",
        "fields1": "f1,f2,f3,f4,f5,f6,f7,f8",
        "fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f62,f63,f64",
        "ut": "7eea3edcaed734bea9cbfc24409ed989",
        "forcect": "1",
    }
    r = requests.get(url, timeout=15, params=params)
    data_json = r.json()
    temp_df = pd.DataFrame([item.split(",") for item in data_json["data"]["klines"]])
    if temp_df.empty: return temp_df
    temp_df.columns = [
        "时间",
        "开盘",
        "收盘",
        "最高",
        "最低",
        "成交量",
        "成交额",
        "-",
        "涨跌幅",
        "涨跌",
        "_",
        "_",
        "持仓量",
        "_",
    ]
    temp_df = temp_df[
        [
            "时间",
            "开盘",
            "最高",
            "最低",
            "收盘",
            "涨跌",
            "涨跌幅",
            "成交量",
            "成交额",
            "持仓量",
        ]
    ]
    temp_df.index = pd.to_datetime(temp_df["时间"])
    temp_df = temp_df[start_date:end_date]
    temp_df.reset_index(drop=True, inplace=True)
    temp_df["开盘"] = pd.to_numeric(temp_df["开盘"], errors="coerce")
    temp_df["收盘"] = pd.to_numeric(temp_df["收盘"], errors="coerce")
    temp_df["最高"] = pd.to_numeric(temp_df["最高"], errors="coerce")
    temp_df["最低"] = pd.to_numeric(temp_df["最低"], errors="coerce")
    temp_df["成交量"] = pd.to_numeric(temp_df["成交量"], errors="coerce")
    temp_df["成交额"] = pd.to_numeric(temp_df["成交额"], errors="coerce")
    temp_df["涨跌"] = pd.to_numeric(temp_df["涨跌"], errors="coerce")
    temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"], errors="coerce")
    temp_df["持仓量"] = pd.to_numeric(temp_df["持仓量"], errors="coerce")
    temp_df["时间"] = pd.to_datetime(temp_df["时间"], errors="coerce").dt.date
    return temp_df


if __name__ == "__main__":
    futures_hist_table_em_df = futures_hist_table_em()
    print(futures_hist_table_em_df)

    futures_hist_em_df = futures_hist_em(symbol="热卷主连", period="daily")
    print(futures_hist_em_df)
