import sys
import os

file_path = os.path.abspath(__file__)
end = file_path.index('mns') + 16
project_path = file_path[0:end]
sys.path.append(project_path)
from loguru import logger
import pandas as pd
import requests
from datetime import datetime
from mns_common.db.MongodbUtil import MongodbUtil
import mns_common.constant.db_name_constant as db_name_constant
import mns_common.utils.data_frame_util as data_frame_util

mongodb_util = MongodbUtil('27017')


def get_tqdm(enable: bool = True):
    """
    返回适用于当前环境的 tqdm 对象。

    Args:
        enable (bool): 是否启用进度条。默认为 True。

    Returns:
        tqdm 对象。
    """
    if not enable:
        # 如果进度条被禁用，返回一个不显示进度条的 tqdm 对象
        return lambda iterable, *args, **kwargs: iterable

    try:
        # 尝试检查是否在 jupyter notebook 环境中，有利于退出进度条
        # noinspection PyUnresolvedReferences
        shell = get_ipython().__class__.__name__
        if shell == "ZMQInteractiveShell":
            from tqdm.notebook import tqdm
        else:
            from tqdm import tqdm
    except (NameError, ImportError):
        # 如果不在 Jupyter 环境中，就使用标准 tqdm
        from tqdm import tqdm

    return tqdm


def stock_gdfx_free_holding_analyse_em(date, is_new):
    """
    东方财富网-数据中心-股东分析-股东持股分析-十大流通股东
    https://data.eastmoney.com/gdfx/HoldingAnalyse.html
    :param date: 报告期
    :type date: str
    :return: 十大流通股东
    :rtype: pandas.DataFrame
    """
    url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
    params = {
        "sortColumns": "UPDATE_DATE,SECURITY_CODE,HOLDER_RANK",
        "sortTypes": "-1,1,1",
        "pageSize": "500",
        "pageNumber": "1",
        "reportName": "RPT_CUSTOM_F10_EH_FREEHOLDERS_JOIN_FREEHOLDER_SHAREANALYSIS",
        "columns": "ALL;D10_ADJCHRATE,D30_ADJCHRATE,D60_ADJCHRATE",
        "source": "WEB",
        "client": "WEB",
        "filter": f"""(LISTING_STATE!=\"10\")(END_DATE='{'-'.join([date[:4], date[4:6], date[6:]])}')""",
    }
    if is_new:
        params.update(
            {"filter": f"""(LISTING_STATE!=\"10\")(END_DATE>='{'-'.join([date[:4], date[4:6], date[6:]])}')"""})
    else:
        params.update(
            {"filter": f"""(LISTING_STATE!=\"10\")(END_DATE='{'-'.join([date[:4], date[4:6], date[6:]])}')"""})
    r = requests.get(url, params=params)
    data_json = r.json()
    total_page = data_json["result"]["pages"]
    temp_big_df = pd.DataFrame()
    tqdm = get_tqdm()
    for page in tqdm(range(1, total_page + 1), leave=False):
        try:
            params.update({"pageNumber": page})
            r = requests.get(url, params=params)
            data_json = r.json()
            temp_df = pd.DataFrame(data_json["result"]["data"])
            temp_big_df = pd.concat(objs=[temp_big_df, temp_df], ignore_index=True)
        except BaseException as e:
            logger.error("获取十大流通股东数据异常:{},{}", str(e), date)

    big_df = temp_big_df.copy()
    big_df.reset_index(inplace=True)
    big_df["index"] = big_df.index + 1
    big_df.rename(
        columns={
            "SECURITY_CODE": "symbol",
            "HOLD_NUM_ABBR": "shareholder_name",
            "HOLDER_TYPE": "shareholder_nature",
            "SHARES_TYPE": "shares_type",
            "HOLD_NUM": "shares_number",
            "FREE_HOLDNUM_RATIO": "circulation_ratio",
            "HOLD_NUM_CHANGE": "change",
            "CHANGE_RATIO": "change_ratio",
            "SECURITY_NAME_ABBR": 'name',
            'HOLDER_STATE': 'holder_state',
            'D10_ADJCHRATE': "d10_adjchrate",
            'D30_ADJCHRATE': "d30_adjchrate",
            'D60_ADJCHRATE': "d60_adjchrate",
            'END_DATE': "end_date",
            'HOLDER_NEWTYPE': 'holder_newtype'

        },
        inplace=True,
    )

    big_df["end_date"] = pd.to_datetime(big_df["end_date"], errors="coerce").dt.date

    big_df["end_date"] = pd.to_datetime(big_df["end_date"]).dt.strftime("%Y-%m-%d")
    # big_df["公告日"] = pd.to_datetime(big_df["公告日"], errors="coerce").dt.date

    big_df["d10_adjchrate"] = pd.to_numeric(
        big_df["d10_adjchrate"], errors="coerce"
    )

    big_df["d60_adjchrate"] = pd.to_numeric(
        big_df["d60_adjchrate"], errors="coerce"
    )

    big_df["d30_adjchrate"] = pd.to_numeric(
        big_df["d30_adjchrate"], errors="coerce"
    )

    big_df["shares_number"] = pd.to_numeric(
        big_df["shares_number"], errors="coerce"
    )
    big_df["circulation_ratio"] = pd.to_numeric(
        big_df["circulation_ratio"], errors="coerce"
    )

    big_df["change_ratio"] = pd.to_numeric(
        big_df["change_ratio"], errors="coerce"
    )

    big_df.loc[:, 'circulation_ratio'] = big_df['circulation_ratio'].fillna(0)
    big_df.loc[:, 'change_ratio'] = big_df['change_ratio'].fillna(0)

    big_df.loc[:, 'd10_adjchrate'] = big_df['d10_adjchrate'].fillna(0)
    big_df.loc[:, 'd30_adjchrate'] = big_df['d30_adjchrate'].fillna(0)
    big_df.loc[:, 'd60_adjchrate'] = big_df['d60_adjchrate'].fillna(0)

    big_df.loc[:, 'holder_state'] = big_df['holder_state'].fillna('不变')

    big_df = big_df[[
        "symbol",
        "shareholder_name",
        "shareholder_nature",
        "shares_type",
        "shares_number",
        "circulation_ratio",
        "change",
        "change_ratio",
        'name',
        'holder_state',
        "d10_adjchrate",
        "d30_adjchrate",
        "d60_adjchrate",
        "end_date",
        "holder_newtype"
    ]]
    big_df['shares_number_str'] = big_df['shares_number'].astype(str)
    big_df['period'] = date

    return big_df


def sync_top_free_gd(period):
    big_df = stock_gdfx_free_holding_analyse_em(period, False)
    now_date = datetime.now()
    sync_time = now_date.strftime('%Y-%m-%d %H:%M:%S')
    create_day = now_date.strftime('%Y-%m-%d')
    big_df['create_day'] = create_day
    big_df['sync_time'] = sync_time
    big_df['update_time'] = sync_time
    big_df['_id'] = big_df['symbol'] + '_' + big_df['period'] + '_' + big_df['shares_number_str']
    query_exist = {'period': period}
    stock_gdfx_top_10_new_df_exist = mongodb_util.find_query_data(db_name_constant.STOCK_GDFX_FREE_TOP_10_NEW,
                                                                  query_exist)
    if data_frame_util.is_not_empty(stock_gdfx_top_10_new_df_exist):
        symbol_mapping_create_day = dict(
            zip(stock_gdfx_top_10_new_df_exist['symbol'], stock_gdfx_top_10_new_df_exist['create_day']))

        symbol_mapping_sync_time = dict(
            zip(stock_gdfx_top_10_new_df_exist['symbol'], stock_gdfx_top_10_new_df_exist['sync_time']))

        big_df['create_day'] = big_df['symbol'].map(
            symbol_mapping_create_day).fillna(create_day)
        big_df['sync_time'] = big_df['symbol'].map(
            symbol_mapping_sync_time).fillna(create_day)

    mongodb_util.save_mongo(big_df, db_name_constant.STOCK_GDFX_FREE_TOP_10_NEW)


def generate_finance_quarter_dates(start_year=1991):
    """
    生成1991年到当前日期的所有财报季度结束日期，格式8位数字（如20251231）
    :param start_year: 起始年份，默认1991
    :return: 倒序列表（最新季度在前），元素为8位数字字符串
    """
    # 财报季度结束月份（固定），对应Q1-Q4
    quarter_end_months = [3, 6, 9, 12]
    # 每个季度结束的日期（固定）
    quarter_end_day = 30 if quarter_end_months in [6, 9] else 31
    # 获取当前时间
    now = datetime.now()
    current_year = now.year
    current_month = now.month

    quarter_dates = []
    # 遍历从起始年到当前年的每一年
    for year in range(start_year, current_year + 1):
        # 遍历每个季度的结束月份
        for month in quarter_end_months:
            # 跳过当前年中「未结束的季度」
            if year == current_year and month > current_month:
                continue
            # 构造季度结束日期（处理3/12月31日，6/9月30日）
            day = 31 if month in (3, 12) else 30
            quarter_date = datetime(year, month, day)
            # 格式化为8位数字字符串（如20251231）
            quarter_dates.append(quarter_date.strftime("%Y%m%d"))

    # 倒序排列：最新季度在前（符合日常查看习惯）
    quarter_dates.reverse()
    return quarter_dates


if __name__ == '__main__':
    quarter_list = generate_finance_quarter_dates()
    for quarter in quarter_list:
        try:
            sync_top_free_gd(quarter)
            logger.info("同步季度到:{}", quarter)
        except BaseException as e:
            logger.error("出现异常:{},{}", e, quarter)
