import time

from tqsdk import TqApi, TqAuth

from tqsdk.tafunc import time_to_datetime

import datetime

import pandas
import re
import os

import warnings
warnings.filterwarnings('ignore')

# pandas.set_option('display.max_columns', None)
# pandas.set_option('display.max_rows', None)

from tqz_extern.json_operator import TQZJsonOperator

TIME_GAP = 8 * 60 * 60 * 1000000000


class TQZTianQinClient:

    __tq_futures = None

    __account: str = 'xxxxxxxxxxxx'
    __pass_word: str = 'xxxxxxxxxxxx'

    def __init__(self, account: str = __account, pass_word: str = __pass_word):
        self.api = TqApi(auth=TqAuth(account, pass_word))

        if TQZTianQinClient.__tq_futures is None:
            TQZTianQinClient.__tq_futures = self.api.query_quotes(ins_class="FUTURE", expired=False)


    def query_history_ticks(self, tq_future: str, tq_data_length: int = 8964):
        assert tq_future in TQZTianQinClient.__tq_futures, f'bad tq_future: {tq_future}'

        tq_result = self.api.get_tick_serial(symbol=tq_future, data_length=tq_data_length)
        self.api.close()

        tq_result['datetime_format'] = tq_result['datetime'].apply(time_to_datetime)

        return tq_result


    def query_single_quote(self, tq_future: str) -> dict:
        result = self.api.get_quote(symbol=tq_future)
        self.api.close()

        return result  # noqa


    def query_history_bars(self, tq_future: str, tq_duration_seconds: int, tq_data_length: int = 8964):
        assert tq_future in TQZTianQinClient.__tq_futures, f'bad tq_future: {tq_future}'

        tq_result = self.api.get_kline_serial(symbol=tq_future, duration_seconds=tq_duration_seconds, data_length=tq_data_length)
        self.api.close()

        tq_result["datetime"] = pandas.to_datetime(tq_result["datetime"] + TIME_GAP)
        tq_result['datetime'] = tq_result['datetime'].apply(lambda x: x.strftime('%Y-%m-%d %H:%M:%S'))  # %f是毫秒

        return tq_result


    def load_all_tq_futures(self):
        self.api.close()
        return TQZTianQinClient.__tq_futures


    def load_all_tq_main_futures(self):
        tq_main_contracts = self.api.query_quotes(ins_class="CONT")

        main_vt_symbols = []
        [main_vt_symbols.append(
            self.api.get_quote(
                symbol=main_contract
            ).underlying_symbol
        ) for main_contract in tq_main_contracts]

        self.api.close()
        return main_vt_symbols

    @classmethod
    def record_data(cls):
        api = TqApi(auth=TqAuth(cls.__account, cls.__pass_word))

        # 如果启用了此备用方案, 将 instruments 换成全品种
        instruments = ["SHFE.cu2305", "DCE.i2309"]
        today = str(datetime.date.today()).replace("-", "")

        quote_map = {}
        data_map = {}  # 之后考虑写共享内存里
        for instrument in instruments:
            quote_map[instrument] = api.get_quote(symbol=instrument)
            data_map[instrument] = pandas.DataFrame()

        while api.wait_update():
            for instrument in instruments:
                if api.is_changing(quote_map[instrument]):
                    # print(quote_map[instrument])
                    data_map[instrument].append(vars(quote_map[instrument]), ignore_index=True)

            # 以国债进行收尾判断(国债最后一分钟的数据不要了), 根据本地时间来进行确认;
            if datetime.datetime.now().hour == 15 and datetime.datetime.now().minute >= 14:
                for instrument in instruments:
                    csv_path = f'./config/{instrument.replace(".", "_")}_{today}.csv'
                    data_map[instrument].to_csv(csv_path, index=False)

                break  # 当前脚本, 每天晚盘前需要手工启动脚本(暂时先这么做, 等程序测试完确认没问题后再在外面加一层每天调度一次的脚本)


    def get_lastDay_mainFuturesList(self) -> (str, list):
        tq_futures = self.api.query_quotes(ins_class="FUTURE", expired=False)
        self.api.close()

        future_instruments_map = {}
        for tq_future in tq_futures:
            simple_future = f'{tq_future.split(".")[0]}.{re.match(r"^[a-zA-Z]{1,3}", tq_future.split(".")[1]).group()}'
            if simple_future not in future_instruments_map.keys():
                future_instruments_map[simple_future] = []

            future_instruments_map[simple_future].append(tq_future)

        time.sleep(5)
        main_futures_list = []
        last_day: str = ''
        for future, instruments in future_instruments_map.items():
            api = TqApi(auth=TqAuth(self.__account, self.__pass_word))
            klines = api.get_kline_serial(instruments, duration_seconds=60 * 60 * 24, data_length=1)

            klines_filter = klines.loc[klines['id'] >= 0]
            klines_filter['datetime_format'] = klines_filter['datetime'].apply(time_to_datetime)

            symbol_maxVolume_map = {}
            for i in range(len(instruments)):
                if i == 0:
                    symbol_maxVolume_map['symbol'] = klines_filter.iloc[0]['symbol']
                    symbol_maxVolume_map['volume'] = klines_filter.iloc[0]['volume']
                else:
                    if klines_filter.iloc[0][f'volume{i}'] > symbol_maxVolume_map['volume']:
                        symbol_maxVolume_map['symbol'] = klines_filter.iloc[0][f'symbol{i}']
                        symbol_maxVolume_map['volume'] = klines_filter.iloc[0][f'volume{i}']

            main_futures_list.append(symbol_maxVolume_map['symbol'])
            if last_day == '':
                last_day = str(time_to_datetime(klines.iloc[0]['datetime'])).split(" ")[0]

            api.close()
            time.sleep(5)

        return last_day, main_futures_list


if __name__ == '__main__':
    # ret_df = TQZTianQinClient().query_history_bars(tq_future="SHFE.cu2305", tq_duration_seconds=60)
    # print("ret_df: " + str(ret_df))

    # ret_df = TQZTianQinClient().query_history_ticks(tq_future="SHFE.rb2310")
    # print("ret_df: " + str(ret_df))

    # TQZTianQinClient.record_data()

    ret = TQZTianQinClient().get_lastDay_mainFuturesList()
    print("ret: " + str(ret))