import os
import sys

file_path = os.path.abspath(__file__)
end = file_path.index('mns') + 17
project_path = file_path[0:end]
sys.path.append(project_path)

from datetime import datetime
import pandas as pd
from loguru import logger
import mns_common.api.ths.ths_stock_api as ths_stock_api
import mns_common.api.em.east_money_stock_v2_api as east_money_stock_v2_api
import mns_scheduler.company_info.company_constant_data as company_constant_data_api
import mns_common.component.common_service_fun_api as common_service_fun_api
import mns_common.component.concept.ths_concept_common_service_api as ths_concept_common_service_api
from mns_common.db.MongodbUtil import MongodbUtil
import mns_common.api.kpl.symbol.kpl_real_time_quotes_api as kpl_real_time_quotes_api
import mns_common.utils.data_frame_util as data_frame_util
import mns_common.api.kpl.constant.kpl_constant as kpl_constant
import mns_common.component.company.company_common_service_api as company_common_service_api

mongodb_util = MongodbUtil('27017')
# 分页大小
MAX_PAGE_NUMBER = 6000
import threading

# 定义一个全局锁，用于保护 result 变量的访问
result_lock = threading.Lock()
# 初始化 result 变量为一个空的 Pandas DataFrame
result = []


# 计算实际流通比例
def calculate_circu_ratio(symbol):
    query = {"symbol": symbol}
    stock_gdfx_free_top_10 = mongodb_util.descend_query(query, 'stock_gdfx_free_top_10', "period", 10)
    if stock_gdfx_free_top_10.shape[0] == 0:
        mv_circulation_ratio = 1
    else:
        # 排除香港结算公司 大于5%减持不用发公告  香港中央结算    HKSCC
        stock_gdfx_free_top_10['is_hk'] = stock_gdfx_free_top_10['shareholder_name'].apply(
            lambda shareholder_name: "HK" if shareholder_name.startswith('香港中央结算') or shareholder_name.startswith(
                'HKSCC') else "A")

        # 持股大于5%      # 排除香港结算公司 大于5%减持不用发公告  香港中央结算    HKSCC
        stock_gdfx_free_top_10 = stock_gdfx_free_top_10.loc[
            (stock_gdfx_free_top_10['circulation_ratio'] >= 5) & (stock_gdfx_free_top_10['is_hk'] == 'A')]

        circulation_ratio = sum(stock_gdfx_free_top_10['circulation_ratio'])
        mv_circulation_ratio = round((100 - circulation_ratio) / 100, 2)
        # 防止错误数据
        if mv_circulation_ratio < 0:
            mv_circulation_ratio = 1
    return mv_circulation_ratio


def filed_sort(company_info):
    return company_info[[
        "_id",
        "name",
        "industry",
        "first_sw_industry",
        "first_industry_code",
        "second_sw_industry",
        "second_industry_code",
        "third_sw_industry",
        "third_industry_code",
        "ths_concept_name",
        "ths_concept_code",
        "ths_concept_sync_day",
        "em_industry",
        "em_concept",
        "business_nature",
        "actual_controller_name",
        "actual_controller_rate",
        "final_controller_name",
        "final_controller_rate",
        "mv_circulation_ratio",
        "flow_mv_sp",
        "total_mv_sp",
        "now_price",
        "total_share",
        "flow_share",
        "total_mv",
        "flow_mv",
        "flow_mv_level",
        "holder_controller_name",
        "holder_controller_rate",
        "area",
        "list_date",
        "pe_ttm",
        "pb",
        "ROE",
        "classification",
        "base_business",
        "address",
        "market_id",
        "symbol",
        "amount",
        "sync_date",
        "ths_concept_list_info",
        "kpl_plate_name",
        "kpl_most_relative_name",
        "kpl_plate_list_info"
    ]]


def get_east_money_stock_info():
    all_real_time_quotes = east_money_stock_v2_api.get_all_real_time_quotes()
    all_real_time_quotes = all_real_time_quotes[['symbol',
                                                 'name',
                                                 "now_price",
                                                 'total_mv',
                                                 'flow_mv',
                                                 'pe_ttm',
                                                 'sz_sh',
                                                 'area',
                                                 'pb',
                                                 'list_date',
                                                 'ROE',
                                                 'total_share',
                                                 'flow_share',
                                                 'industry',
                                                 'amount',
                                                 'concept']]

    all_real_time_quotes = common_service_fun_api.exclude_b_symbol(all_real_time_quotes)
    return all_real_time_quotes


def create_index():
    mongodb_util.create_index('company_info',
                              [("classification", 1)])
    mongodb_util.create_index('company_info',
                              [("industry", 1)])
    mongodb_util.create_index('company_info',
                              [("flow_mv", 1)])
    mongodb_util.create_index('company_info',
                              [("list_date", 1)])
    mongodb_util.create_index('company_info',
                              [("symbol", 1)])


# 修改行业信息
def fix_company_industry(symbol):
    if symbol is not None:
        query = {"symbol": symbol}
        company_info = mongodb_util.find_query_data('company_info_base', query)
    else:
        company_info = mongodb_util.find_all_data('company_info_base')

    company_info = company_info.set_index(['second_sw_industry'], drop=False)
    del company_info['industry']
    # fix industry  name
    industry_final_fix_df = company_constant_data_api.get_industry_final_fix_df()
    industry_final_fix_df = industry_final_fix_df.set_index(['second_sw_industry'], drop=True)
    company_info = pd.merge(company_info, industry_final_fix_df, how='outer',
                            left_index=True, right_index=True)
    # 将申万第三行业做为行业
    company_info = company_constant_data_api.fix_industry_use_sw_third(company_info.copy())
    company_info['industry'] = company_info['industry'].fillna('综合')
    company_info = filed_sort(company_info)
    company_info['company_type'] = company_info['business_nature']

    # 将list_date列中的所有NaN值设置为99990909
    company_info['list_date'].fillna(20990909.0, inplace=True)

    # 将日期数值转换为日期时间格式
    company_info['list_date_01'] = pd.to_datetime(company_info['list_date'], format='%Y%m%d')

    company_info['list_date'] = company_info['list_date'].apply(
        lambda x: pd.to_numeric(x, errors="coerce"))

    now_date = datetime.now()

    # 计算日期差值 距离现在上市时间
    company_info['diff_days'] = company_info.apply(
        lambda row: (now_date - row['list_date_01']).days, axis=1)

    str_now_date = now_date.strftime('%Y-%m-%d %H:%M:%S')
    company_info['sync_date'] = str_now_date

    try:
        # 次新股
        sub_stock = ths_stock_api.ths_stock_concept('885598')
        sub_stock_symbol_list = list(sub_stock['symbol'])
    except BaseException as e:
        query = {'concept_code': 885598}
        ths_stock_concept_detail = mongodb_util.find_query_data('ths_stock_concept_detail', query)
        sub_stock_symbol_list = list(ths_stock_concept_detail['symbol'])
    company_info.loc[:, 'sub_stock'] = False
    company_info.loc[company_info['symbol'].isin(sub_stock_symbol_list), 'sub_stock'] = True

    try:
        company_info.dropna(subset=['symbol'], axis=0, inplace=True)
        company_info.dropna(subset=['_id'], axis=0, inplace=True)
        mongodb_util.save_mongo(company_info, 'company_info')
    except BaseException as e:
        logger.error("出现异常:{}", symbol)

    return company_info


def sync_company_base_info(symbol_list):
    global result
    result = []
    create_index()
    east_money_stock_info = get_east_money_stock_info()
    east_money_stock_info = east_money_stock_info.loc[~(
        east_money_stock_info['symbol'].isin(company_constant_data_api.de_listed_stock_list))]
    east_money_stock_info = common_service_fun_api.exclude_ts_symbol(east_money_stock_info)
    east_money_stock_info = east_money_stock_info.loc[~((east_money_stock_info['industry'] == '-')
                                                        & (east_money_stock_info['now_price'] == 0))]

    east_money_stock_info = common_service_fun_api.total_mv_classification(east_money_stock_info)
    east_money_stock_info = common_service_fun_api.classify_symbol(east_money_stock_info)

    # 将日期数值转换为日期时间格式
    east_money_stock_info['list_date_01'] = pd.to_datetime(east_money_stock_info['list_date'], format='%Y%m%d')

    # 开票啦实时数据
    kpl_real_time_quotes = kpl_real_time_quotes_api.get_kpl_real_time_quotes()

    if symbol_list is not None:
        east_money_stock_info = east_money_stock_info.loc[east_money_stock_info['symbol'].isin(symbol_list)]
    count = east_money_stock_info.shape[0]
    page_number = round(count / MAX_PAGE_NUMBER, 0) + 1
    page_number = int(page_number)
    threads = []
    # 创建多个线程来获取数据
    for page in range(page_number):  # 0到100页
        end_count = (page + 1) * MAX_PAGE_NUMBER
        begin_count = page * MAX_PAGE_NUMBER
        page_df = east_money_stock_info.loc[begin_count:end_count]
        thread = threading.Thread(target=single_thread_sync_company_info, args=(page_df, kpl_real_time_quotes))
        threads.append(thread)
        thread.start()

    # 等待所有线程完成
    for thread in threads:
        thread.join()

    fail_df = east_money_stock_info.loc[east_money_stock_info['symbol'].isin(result)]
    single_thread_sync_company_info(fail_df, kpl_real_time_quotes)


def single_thread_sync_company_info(east_money_stock_info,
                                    kpl_real_time_quotes):
    global result
    fail_list = []
    for company_one in east_money_stock_info.itertuples():
        try:
            company_info_type = ths_stock_api.get_company_info_detail(company_one.symbol)
            company_info_type['first_industry_code'] = company_info_type['hycode'].apply(
                lambda x: x[1:3] + '0000')
            company_info_type['second_industry_code'] = company_info_type['hy2code'].apply(
                lambda x: x[1:5] + '00')
            company_info_type['third_industry_code'] = company_info_type['hy3code'].apply(
                lambda x: x[1:7])

            company_info_type['first_sw_industry'] = company_info_type['hy']
            company_info_type['second_sw_industry'] = company_info_type['hy2']
            company_info_type['third_sw_industry'] = company_info_type['hy3']
            # 保存申万行业信息
            save_sw_data(company_info_type)

            company_info_type['_id'] = company_one.symbol

            company_info_type['name'] = company_one.name

            company_info_type['em_industry'] = company_one.industry
            company_info_type['em_concept'] = company_one.concept

            company_info_type['now_price'] = company_one.now_price
            company_info_type['total_share'] = company_one.total_share
            company_info_type['flow_share'] = company_one.flow_share
            company_info_type['total_mv'] = company_one.total_mv
            company_info_type['flow_mv'] = company_one.flow_mv
            company_info_type['area'] = company_one.area
            company_info_type['list_date'] = company_one.list_date
            now_date = datetime.now()
            # 计算日期差值 距离现在上市时间
            company_info_type['diff_days'] = (now_date - company_one.list_date_01).days

            company_info_type['pe_ttm'] = company_one.pe_ttm
            company_info_type['pb'] = company_one.pb
            company_info_type['ROE'] = company_one.ROE
            company_info_type['flow_mv_sp'] = company_one.flow_mv_sp
            company_info_type['total_mv_sp'] = company_one.total_mv_sp
            company_info_type['flow_mv_level'] = company_one.flow_mv_level
            company_info_type['classification'] = company_one.classification
            company_info_type['mv_circulation_ratio'] = calculate_circu_ratio(company_one.symbol)
            # 获取同花顺最新概念
            company_info_type = ths_concept_common_service_api.set_ths_concept(company_one.symbol, company_info_type)
            now_date = datetime.now()
            str_now_date = now_date.strftime('%Y-%m-%d %H:%M:%S')
            company_info_type['sync_date'] = str_now_date

            if company_one.symbol in company_constant_data_api.fix_symbol_list:
                # fix sw_industry
                company_info_type = company_constant_data_api.fix_symbol_industry(company_info_type, company_one.symbol)

            # todo fix industry
            company_info_type['industry'] = company_info_type['second_sw_industry']
            company_info_type['amount'] = company_one.amount

            company_info_type['kpl_plate_list_info'] = '-'
            company_info_type['kpl_plate_name'] = '-'
            company_info_type['kpl_most_relative_name'] = '-'

            try:
                if data_frame_util.is_not_empty(kpl_real_time_quotes):
                    kpl_real_time_quotes_one = kpl_real_time_quotes.loc[
                        kpl_real_time_quotes['symbol'] == company_one.symbol]

                    if data_frame_util.is_not_empty(kpl_real_time_quotes_one):
                        company_info_type['kpl_plate_name'] = list(kpl_real_time_quotes_one['plate_name_list'])[0]
                        company_info_type['kpl_most_relative_name'] = \
                            list(kpl_real_time_quotes_one['most_relative_name'])[
                                0]
                    company_info_type = set_kpl_data(kpl_real_time_quotes_one, company_info_type, company_one)

                if bool(1 - ("kpl_plate_name" in company_info_type.columns)) or bool(
                        1 - ("kpl_most_relative_name" in company_info_type.columns)):
                    company_info_type['kpl_plate_name'] = ""
                    company_info_type['kpl_most_relative_name'] = ""
            except BaseException as e:
                logger.warning("设置开盘啦数据异常:{},{}", company_one.symbol, e)

            company_info_type = filed_sort(company_info_type)
            mongodb_util.save_mongo(company_info_type.copy(), 'company_info_base')
            logger.info("同步公司信息完成:{}", company_one.symbol + '-' + company_one.name)
        except BaseException as e:
            fail_list.append(company_one.symbol)
            logger.error("同步公司信息发生异常:{},{}", company_one.symbol, e)
    with result_lock:
        # 使用锁来保护 result 变量的访问，将每页的数据添加到结果中
        result = fail_list


def set_kpl_data(kpl_real_time_quotes_one, company_info_type, company_one):
    if data_frame_util.is_not_empty(kpl_real_time_quotes_one):
        company_info_type['kpl_plate_name'] = list(kpl_real_time_quotes_one['plate_name_list'])[0]
        company_info_type['kpl_most_relative_name'] = list(kpl_real_time_quotes_one['most_relative_name'])[
            0]
        symbol = company_one.symbol

        query = {'symbol': symbol, "index_class": kpl_constant.FIRST_INDEX}
        kpl_best_choose_index_detail = mongodb_util.find_query_data('kpl_best_choose_index_detail', query)
        if data_frame_util.is_not_empty(kpl_best_choose_index_detail):
            kpl_best_choose_index_detail = kpl_best_choose_index_detail[[
                "plate_code",
                "plate_name",
                "first_plate_code",
                "first_plate_name",
                "index_class"
            ]]

            # 去除空格
            kpl_best_choose_index_detail['plate_name'] = kpl_best_choose_index_detail['plate_name'].str.replace(' ', '')
            # 去除空格
            kpl_best_choose_index_detail['first_plate_name'] = kpl_best_choose_index_detail[
                'first_plate_name'].str.replace(' ', '')

            company_info_type.loc[:, 'kpl_plate_list_info'] = kpl_best_choose_index_detail.to_string(index=False)
    return company_info_type


# 更新新上市公司信息
def new_company_info_update():
    east_money_stock_info = get_east_money_stock_info()
    new_stock = common_service_fun_api.get_new_stock(east_money_stock_info)
    for company_one in new_stock.itertuples():
        try:
            sync_company_base_info([company_one.symbol])
            fix_company_industry(company_one.symbol)

        except BaseException as e:
            logger.error("出现异常:{}", e)
    company_common_service_api.company_info_industry_cache_clear


# 保存申万行业分类
def save_sw_data(company_info_type):
    first_sw_info = company_info_type[[
        'first_sw_industry',
        'first_industry_code'
    ]].copy()

    first_sw_info.loc[:, "industry_code"] = first_sw_info['first_industry_code']
    first_sw_info.loc[:, "_id"] = first_sw_info['first_industry_code']
    first_sw_info.loc[:, "second_sw_industry"] = 0
    first_sw_info.loc[:, "third_sw_industry"] = 0
    first_sw_info.loc[:, "second_industry_code"] = 0
    first_sw_info.loc[:, "third_industry_code"] = 0
    first_sw_info = first_sw_info[[
        "_id",
        "industry_code",
        'first_industry_code',
        'first_sw_industry',
        'second_industry_code',
        'second_sw_industry',
        'third_industry_code',
        'third_sw_industry'
    ]]
    mongodb_util.save_mongo(first_sw_info, 'sw_industry')

    second_sw_info = company_info_type[[
        'first_industry_code',
        'first_sw_industry',
        'second_sw_industry',
        'second_industry_code',
    ]].copy()

    second_sw_info.loc[:, "industry_code"] = second_sw_info['second_industry_code']
    second_sw_info.loc[:, "_id"] = second_sw_info['industry_code']

    second_sw_info.loc[:, "third_sw_industry"] = 0
    second_sw_info.loc[:, "third_sw_industry"] = 0
    second_sw_info.loc[:, "third_industry_code"] = 0
    second_sw_info = second_sw_info[[
        "_id",
        "industry_code",
        'first_industry_code',
        'first_sw_industry',
        'second_industry_code',
        'second_sw_industry',
        'third_industry_code',
        'third_sw_industry'
    ]]
    mongodb_util.save_mongo(second_sw_info, 'sw_industry')

    third_sw_info = company_info_type[[
        'first_industry_code',
        'first_sw_industry',
        'second_industry_code',
        'second_sw_industry',
        'third_industry_code',
        'third_sw_industry'
    ]].copy()

    third_sw_info.loc[:, "industry_code"] = third_sw_info['third_industry_code']

    third_sw_info.loc[:, "_id"] = third_sw_info['industry_code']

    third_sw_info = third_sw_info[[
        "_id",
        "industry_code",
        'first_industry_code',
        'first_sw_industry',
        'second_industry_code',
        'second_sw_industry',
        'third_industry_code',
        'third_sw_industry'
    ]]
    mongodb_util.save_mongo(third_sw_info, 'sw_industry')


if __name__ == '__main__':
    # while True:
    #     df = ths_stock_api.get_company_info_detail('000001')
    #     print(df)
    # company_info_update()
    # company_info_type = ths_stock_api.get_company_info_detail('836699')
    # sync_company_base_info()
    # fix_company_industry()
    # calculate_circu_ratio("601069")
    # sync_company_base_info()
    # 300293
    # sync_company_base_info(None)
    new_company_info_update()
    sync_company_base_info(None)
    fix_company_industry(None)
    # group_by_industry()
