# coding: utf-8
import calendar
import json.decoder
import sys
import os
from copy import copy
from datetime import date, datetime, timedelta

import airflow.configuration
import openpyxl
import openpyxl.styles
import openpyxl.utils.datetime
from openpyxl.workbook import  Workbook
from airflow.providers.mysql.hooks.mysql import MySqlHook

from common.excel_clickhouse_processor import ClickHouseExcelProcessor
from utils import clickhouse, get_file_content, get_splitted_sql



def generate_wealth_report(p_rpt_date, result_file_path):
    """生成财富管理报表结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/wealth_report_template.xlsx",
    )
    sql_summary_daily = get_file_content("sql/ads/wealth_report/summary_daily.sql")
    sql_summary_weekly = get_file_content("sql/ads/wealth_report/summary_weekly.sql")
    sql_detail_metric = get_file_content("sql/ads/wealth_report/detail_metric.sql")
    sql_detail_online_offline = get_file_content(
        "sql/ads/wealth_report/detail_online_offline.sql"
    )
    sql_detail_channel = get_file_content("sql/ads/wealth_report/detail_channel.sql")

    p_rpt_date = p_rpt_date.strftime("%Y-%m-%d")

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)
    worksheet_summary_daily = workbook["日简报"]
    worksheet_summary_weekly = workbook["周简报"]
    worksheet_detail = workbook["每日数据"]

    # 1. 日简报
    (
        rpt_date,
        account_num_new_individual_ths,
        account_num_new_individual_other,
        valid_rate,
        valid_change_type,
        paying_rate,
        paying_change_type,
        pi_rate,
        pi_change_type,
        account_num_new_individual,
        valid_num_new_individual,
        paying_num_new_individual,
        pi_num_new_individual,
        aum_individual_10k,
        account_num_new_individual_change_rate_1w,
        valid_num_new_individual_change_rate_1w,
        paying_num_new_individual_change_rate_1w,
        pi_num_new_individual_change_rate_1w,
        aum_individual_change_rate_1w,
        account_num_new_individual_avg,
        valid_num_new_individual_avg,
        paying_num_new_individual_avg,
        pi_num_new_individual_avg,
        aum_individual_avg_10k,
        account_num_new_individual_change_rate_week,
        valid_num_new_individual_change_rate_week,
        paying_num_new_individual_change_rate_week,
        pi_num_new_individual_change_rate_week,
        aum_individual_change_rate_week,
    ) = ads_hook.get_first(sql_summary_daily.format(p_rpt_date=p_rpt_date))

    rpt_date = _to_date(rpt_date)

    a1 = f"【{rpt_date.month}月{rpt_date.day}日日简报】"
    a3 = f"同花顺渠道新增开户{account_num_new_individual_ths}人，其他渠道新增开户{account_num_new_individual_other}人。"

    a5_valid_change = _change_type_str(valid_change_type)
    a5_paying_change = _change_type_str(paying_change_type)
    a5_pi_change = _change_type_str(pi_change_type)
    a5 = (
        f"当前有效户占总体{valid_rate:.2%}{a5_valid_change}；付费客户占总体{paying_rate:.2%}{a5_paying_change}；"
        f"高净值客户占总体{pi_rate:.2%}{a5_pi_change}。"
    )

    worksheet_summary_daily["A1"].value = a1
    worksheet_summary_daily["A7"].value = a1
    worksheet_summary_daily["A3"].value = a3
    worksheet_summary_daily["A5"].value = a5

    worksheet_summary_daily["C9"].value = account_num_new_individual
    worksheet_summary_daily["C10"].value = valid_num_new_individual
    worksheet_summary_daily["C11"].value = paying_num_new_individual
    worksheet_summary_daily["C12"].value = pi_num_new_individual
    worksheet_summary_daily["C13"].value = _to_float(aum_individual_10k)

    worksheet_summary_daily["D9"].value = _to_float(
        account_num_new_individual_change_rate_1w
    )
    worksheet_summary_daily["D10"].value = _to_float(
        valid_num_new_individual_change_rate_1w
    )
    worksheet_summary_daily["D11"].value = _to_float(
        paying_num_new_individual_change_rate_1w
    )
    worksheet_summary_daily["D12"].value = _to_float(
        pi_num_new_individual_change_rate_1w
    )
    worksheet_summary_daily["D13"].value = _to_float(aum_individual_change_rate_1w)

    worksheet_summary_daily["E9"].value = _to_float(account_num_new_individual_avg)
    worksheet_summary_daily["E10"].value = _to_float(valid_num_new_individual_avg)
    worksheet_summary_daily["E11"].value = _to_float(paying_num_new_individual_avg)
    worksheet_summary_daily["E12"].value = _to_float(pi_num_new_individual_avg)
    worksheet_summary_daily["E13"].value = _to_float(aum_individual_avg_10k)

    worksheet_summary_daily["F9"].value = _to_float(
        account_num_new_individual_change_rate_week
    )
    worksheet_summary_daily["F10"].value = _to_float(
        valid_num_new_individual_change_rate_week
    )
    worksheet_summary_daily["F11"].value = _to_float(
        paying_num_new_individual_change_rate_week
    )
    worksheet_summary_daily["F12"].value = _to_float(
        pi_num_new_individual_change_rate_week
    )
    worksheet_summary_daily["F13"].value = _to_float(aum_individual_change_rate_week)

    # 2. 周简报
    (
        this_week_start,
        rpt_date,
        prev_week_start,
        prev_week_end,
        prev_2week_start,
        prev_2week_end,
        prev_month_end,
        account_num_new_individual_ths_total,
        account_num_new_individual_other_total,
        valid_rate,
        valid_change_type,
        paying_rate,
        paying_change_type,
        pi_rate,
        pi_change_type,
        account_num_new_individual_total_tw,
        account_num_new_individual_avg_trade_tw,
        account_num_new_individual_ytd_tw,
        valid_num_new_individual_ytd_tw,
        cash_net_movement_ytd_10k_tw,
        cash_net_movement_ytd_10k_avg_tw,
        account_num_individual_acc_tw,
        valid_num_individual_avg_tw,
        paying_num_individual_avg_tw,
        aum_individual_10k_tw,
        account_num_new_individual_total_pw,
        account_num_new_individual_avg_trade_pw,
        account_num_new_individual_ytd_pw,
        valid_num_new_individual_ytd_pw,
        cash_net_movement_ytd_10k_pw,
        cash_net_movement_ytd_10k_avg_pw,
        account_num_individual_acc_pw,
        valid_num_individual_avg_pw,
        paying_num_individual_avg_pw,
        aum_individual_10k_pw,
        account_num_new_individual_total_p2w,
        account_num_new_individual_avg_trade_p2w,
        account_num_new_individual_ytd_p2w,
        valid_num_new_individual_ytd_p2w,
        cash_net_movement_ytd_10k_p2w,
        cash_net_movement_ytd_10k_avg_p2w,
        account_num_individual_acc_p2w,
        valid_num_individual_avg_p2w,
        paying_num_individual_avg_p2w,
        aum_individual_10k_p2w,
        account_num_new_individual_total_change_rate_week,
        account_num_new_individual_avg_trade_change_rate_week,
        account_num_new_individual_ytd_change_rate_week,
        valid_num_new_individual_ytd_change_rate_week,
        cash_net_movement_ytd_change_rate_week,
        cash_net_movement_ytd_avg_change_rate_week,
        account_num_individual_acc_change_rate_week,
        valid_num_individual_avg_change_rate_week,
        paying_num_individual_avg_change_rate_week,
        aum_individual_change_rate_week,
        account_num_new_individual_total_tm,
        account_num_new_individual_avg_trade_tm,
        account_num_new_individual_ytd_tm,
        valid_num_new_individual_ytd_tm,
        cash_net_movement_ytd_10k_tm,
        cash_net_movement_ytd_10k_avg_tm,
        account_num_individual_acc_tm,
        valid_num_individual_avg_tm,
        paying_num_individual_avg_tm,
        aum_individual_10k_tm,
        account_num_new_individual_total_pm,
        account_num_new_individual_avg_trade_pm,
        account_num_new_individual_ytd_pm,
        valid_num_new_individual_ytd_pm,
        cash_net_movement_ytd_10k_pm,
        cash_net_movement_ytd_10k_avg_pm,
        account_num_individual_acc_pm,
        valid_num_individual_avg_pm,
        paying_num_individual_avg_pm,
        aum_individual_10k_pm,
        account_num_new_individual_total_change_rate_month,
        account_num_new_individual_avg_trade_change_rate_month,
        account_num_new_individual_ytd_change_rate_month,
        valid_num_new_individual_ytd_change_rate_month,
        cash_net_movement_ytd_change_rate_month,
        cash_net_movement_ytd_avg_change_rate_month,
        account_num_individual_acc_change_rate_month,
        valid_num_individual_avg_change_rate_month,
        paying_num_individual_avg_change_rate_month,
        aum_individual_change_rate_month,
    ) = ads_hook.get_first(sql_summary_weekly.format(p_rpt_date=p_rpt_date))

    this_week_start = _to_date(this_week_start)
    rpt_date = _to_date(rpt_date)
    prev_week_start = _to_date(prev_week_start)
    prev_week_end = _to_date(prev_week_end)
    prev_2week_start = _to_date(prev_2week_start)
    prev_2week_end = _to_date(prev_2week_end)
    prev_month_end = _to_date(prev_month_end)

    a1 = f"【{this_week_start.month}月{this_week_start.day}日-{rpt_date.month}月{rpt_date.day}日周简报】"
    a3 = f"同花顺渠道新增开户{account_num_new_individual_ths_total}人，其他渠道新增开户{account_num_new_individual_other_total}人。"

    a5_valid_change = _change_type_str(valid_change_type)
    a5_paying_change = _change_type_str(paying_change_type)
    a5_pi_change = _change_type_str(pi_change_type)
    a5 = (
        f"当前有效户占总体{valid_rate:.2%}{a5_valid_change}；付费客户占总体{paying_rate:.2%}{a5_paying_change}；"
        f"高净值客户占总体{pi_rate:.2%}{a5_pi_change}。"
    )

    d8 = f"本周（{this_week_start.month}.{this_week_start.day}-{rpt_date.month}.{rpt_date.day}）"
    e8 = f"上周（{prev_week_start.month}.{prev_week_start.day}-{prev_week_end.month}.{prev_week_end.day})"
    f8 = f"上上周（{prev_2week_start.month}.{prev_2week_start.day}-{prev_2week_end.month}.{prev_2week_end.day})"
    h8 = f"本月累计（截至{rpt_date.month}.{rpt_date.day}）"
    i8 = f"上月同期累计（截至{prev_month_end.month}.{prev_month_end.day}）"

    worksheet_summary_weekly["A1"].value = a1
    worksheet_summary_weekly["A7"].value = a1
    worksheet_summary_weekly["A3"].value = a3
    worksheet_summary_weekly["A5"].value = a5

    worksheet_summary_weekly["D8"].value = d8
    worksheet_summary_weekly["E8"].value = e8
    worksheet_summary_weekly["F8"].value = f8
    worksheet_summary_weekly["H8"] = h8
    worksheet_summary_weekly["I8"] = i8

    worksheet_summary_weekly["D9"] = account_num_new_individual_total_tw
    worksheet_summary_weekly["D10"] = account_num_new_individual_avg_trade_tw
    worksheet_summary_weekly["D11"] = account_num_new_individual_ytd_tw
    worksheet_summary_weekly["D12"] = valid_num_new_individual_ytd_tw
    worksheet_summary_weekly["D13"] = _to_float(cash_net_movement_ytd_10k_tw)
    worksheet_summary_weekly["D14"] = _to_float(cash_net_movement_ytd_10k_avg_tw)
    worksheet_summary_weekly["D15"] = account_num_individual_acc_tw
    worksheet_summary_weekly["D16"] = valid_num_individual_avg_tw
    worksheet_summary_weekly["D17"] = paying_num_individual_avg_tw
    worksheet_summary_weekly["D18"] = _to_float(aum_individual_10k_tw)

    worksheet_summary_weekly["E9"] = account_num_new_individual_total_pw
    worksheet_summary_weekly["E10"] = account_num_new_individual_avg_trade_pw
    worksheet_summary_weekly["E11"] = account_num_new_individual_ytd_pw
    worksheet_summary_weekly["E12"] = valid_num_new_individual_ytd_pw
    worksheet_summary_weekly["E13"] = _to_float(cash_net_movement_ytd_10k_pw)
    worksheet_summary_weekly["E14"] = _to_float(cash_net_movement_ytd_10k_avg_pw)
    worksheet_summary_weekly["E15"] = account_num_individual_acc_pw
    worksheet_summary_weekly["E16"] = valid_num_individual_avg_pw
    worksheet_summary_weekly["E17"] = paying_num_individual_avg_pw
    worksheet_summary_weekly["E18"] = _to_float(aum_individual_10k_pw)

    worksheet_summary_weekly["F9"] = account_num_new_individual_total_p2w
    worksheet_summary_weekly["F10"] = account_num_new_individual_avg_trade_p2w
    worksheet_summary_weekly["F11"] = account_num_new_individual_ytd_p2w
    worksheet_summary_weekly["F12"] = valid_num_new_individual_ytd_p2w
    worksheet_summary_weekly["F13"] = _to_float(cash_net_movement_ytd_10k_p2w)
    worksheet_summary_weekly["F14"] = _to_float(cash_net_movement_ytd_10k_avg_p2w)
    worksheet_summary_weekly["F15"] = account_num_individual_acc_p2w
    worksheet_summary_weekly["F16"] = valid_num_individual_avg_p2w
    worksheet_summary_weekly["F17"] = paying_num_individual_avg_p2w
    worksheet_summary_weekly["F18"] = _to_float(aum_individual_10k_p2w)

    worksheet_summary_weekly["G9"] = _to_float(
        account_num_new_individual_total_change_rate_week
    )
    worksheet_summary_weekly["G10"] = _to_float(
        account_num_new_individual_avg_trade_change_rate_week
    )
    worksheet_summary_weekly["G11"] = _to_float(
        account_num_new_individual_ytd_change_rate_week
    )
    worksheet_summary_weekly["G12"] = _to_float(
        valid_num_new_individual_ytd_change_rate_week
    )
    worksheet_summary_weekly["G13"] = _to_float(cash_net_movement_ytd_change_rate_week)
    worksheet_summary_weekly["G14"] = _to_float(
        cash_net_movement_ytd_avg_change_rate_week
    )
    worksheet_summary_weekly["G15"] = _to_float(
        account_num_individual_acc_change_rate_week
    )
    worksheet_summary_weekly["G16"] = _to_float(
        valid_num_individual_avg_change_rate_week
    )
    worksheet_summary_weekly["G17"] = _to_float(
        paying_num_individual_avg_change_rate_week
    )
    worksheet_summary_weekly["G18"] = _to_float(aum_individual_change_rate_week)

    worksheet_summary_weekly["H9"] = account_num_new_individual_total_tm
    worksheet_summary_weekly["H10"] = account_num_new_individual_avg_trade_tm
    worksheet_summary_weekly["H11"] = account_num_new_individual_ytd_tm
    worksheet_summary_weekly["H12"] = valid_num_new_individual_ytd_tm
    worksheet_summary_weekly["H13"] = _to_float(cash_net_movement_ytd_10k_tm)
    worksheet_summary_weekly["H14"] = _to_float(cash_net_movement_ytd_10k_avg_tm)
    worksheet_summary_weekly["H15"] = account_num_individual_acc_tm
    worksheet_summary_weekly["H16"] = valid_num_individual_avg_tm
    worksheet_summary_weekly["H17"] = paying_num_individual_avg_tm
    worksheet_summary_weekly["H18"] = _to_float(aum_individual_10k_tm)

    worksheet_summary_weekly["I9"] = account_num_new_individual_total_pm
    worksheet_summary_weekly["I10"] = account_num_new_individual_avg_trade_pm
    worksheet_summary_weekly["I11"] = account_num_new_individual_ytd_pm
    worksheet_summary_weekly["I12"] = valid_num_new_individual_ytd_pm
    worksheet_summary_weekly["I13"] = _to_float(cash_net_movement_ytd_10k_pm)
    worksheet_summary_weekly["I14"] = _to_float(cash_net_movement_ytd_10k_avg_pm)
    worksheet_summary_weekly["I15"] = account_num_individual_acc_pm
    worksheet_summary_weekly["I16"] = valid_num_individual_avg_pm
    worksheet_summary_weekly["I17"] = paying_num_individual_avg_pm
    worksheet_summary_weekly["I18"] = _to_float(aum_individual_10k_pm)

    worksheet_summary_weekly["J9"] = _to_float(
        account_num_new_individual_total_change_rate_month
    )
    worksheet_summary_weekly["J10"] = _to_float(
        account_num_new_individual_avg_trade_change_rate_month
    )
    worksheet_summary_weekly["J11"] = _to_float(
        account_num_new_individual_ytd_change_rate_month
    )
    worksheet_summary_weekly["J12"] = _to_float(
        valid_num_new_individual_ytd_change_rate_month
    )
    worksheet_summary_weekly["J13"] = _to_float(cash_net_movement_ytd_change_rate_month)
    worksheet_summary_weekly["J14"] = _to_float(
        cash_net_movement_ytd_avg_change_rate_month
    )
    worksheet_summary_weekly["J15"] = _to_float(
        account_num_individual_acc_change_rate_month
    )
    worksheet_summary_weekly["J16"] = _to_float(
        valid_num_individual_avg_change_rate_month
    )
    worksheet_summary_weekly["J17"] = _to_float(
        paying_num_individual_avg_change_rate_month
    )
    worksheet_summary_weekly["J18"] = _to_float(aum_individual_change_rate_month)

    # 3. 每日数据-总览
    row_num = 4
    for row in ads_hook.get_records(sql_detail_metric.format(p_rpt_date=p_rpt_date)):
        (
            stats_date,
            account_num_new_individual,
            valid_num_new_individual,
            paying_num_new_individual,
            pi_num_new_individual,
            trade_num_individual,
            wealth_buy_num_individual,
            margin_trade_num,
            acc_trade_num_individual_rate,
            acc_wealth_buy_num_individual_rate,
            acc_margin_trade_num_rate,
            nonwealth_market_value_individual_10k_avg,
            wealth_market_value_individual_10k_avg,
            debit_principal_individual_100m,
            t1m_all_revenue_individual_avg_trade,
            t1m_all_revenue_individual_avg_valid,
            account_num_new_organization,
            trade_amount_organization_rate,
        ) = row

        stats_date = _to_date(stats_date)
        stats_date_num = openpyxl.utils.datetime.to_excel(stats_date)

        worksheet_detail[f"A{row_num}"].value = stats_date_num
        worksheet_detail[f"B{row_num}"].value = account_num_new_individual
        worksheet_detail[f"C{row_num}"].value = valid_num_new_individual
        worksheet_detail[f"D{row_num}"].value = paying_num_new_individual
        worksheet_detail[f"E{row_num}"].value = pi_num_new_individual
        worksheet_detail[f"F{row_num}"].value = trade_num_individual
        worksheet_detail[f"G{row_num}"].value = wealth_buy_num_individual
        worksheet_detail[f"H{row_num}"].value = margin_trade_num
        worksheet_detail[f"I{row_num}"].value = _to_float(acc_trade_num_individual_rate)
        worksheet_detail[f"J{row_num}"].value = _to_float(
            acc_wealth_buy_num_individual_rate
        )
        worksheet_detail[f"K{row_num}"].value = _to_float(acc_margin_trade_num_rate)
        worksheet_detail[f"L{row_num}"].value = _to_float(
            nonwealth_market_value_individual_10k_avg
        )
        worksheet_detail[f"M{row_num}"].value = _to_float(
            wealth_market_value_individual_10k_avg
        )
        worksheet_detail[f"N{row_num}"].value = _to_float(
            debit_principal_individual_100m
        )
        worksheet_detail[f"O{row_num}"].value = _to_float(
            t1m_all_revenue_individual_avg_trade
        )
        worksheet_detail[f"P{row_num}"].value = _to_float(
            t1m_all_revenue_individual_avg_valid
        )
        worksheet_detail[f"Q{row_num}"].value = account_num_new_organization
        worksheet_detail[f"R{row_num}"].value = _to_float(
            trade_amount_organization_rate
        )

        row_num += 1

    # 4. 每日数据-线上线下核心指标
    row_num = 39
    for row in ads_hook.get_records(
        sql_detail_online_offline.format(p_rpt_date=p_rpt_date)
    ):
        (
            stats_date,
            account_num_new_individual_online,
            account_num_new_individual_offline,
            valid_num_new_individual_online,
            valid_num_new_individual_offline,
            pi_num_new_individual_online,
            pi_num_new_individual_offline,
            aum_individual_online_change_10k,
            aum_individual_offline_offline_change_10k,
            wealth_market_value_individual_online_change_10k,
            wealth_market_value_individual_offline_change_10k,
            account_num_new_organization_online,
            account_num_new_organization_offline,
        ) = row

        stats_date = _to_date(stats_date)
        stats_date_num = openpyxl.utils.datetime.to_excel(stats_date)

        worksheet_detail[f"A{row_num}"].value = stats_date_num
        worksheet_detail[f"B{row_num}"].value = account_num_new_individual_online
        worksheet_detail[f"C{row_num}"].value = account_num_new_individual_offline
        worksheet_detail[f"D{row_num}"].value = valid_num_new_individual_online
        worksheet_detail[f"E{row_num}"].value = valid_num_new_individual_offline
        worksheet_detail[f"F{row_num}"].value = pi_num_new_individual_online
        worksheet_detail[f"G{row_num}"].value = pi_num_new_individual_offline
        worksheet_detail[f"H{row_num}"].value = _to_float(
            aum_individual_online_change_10k
        )
        worksheet_detail[f"I{row_num}"].value = _to_float(
            aum_individual_offline_offline_change_10k
        )
        worksheet_detail[f"J{row_num}"].value = _to_float(
            wealth_market_value_individual_online_change_10k
        )
        worksheet_detail[f"K{row_num}"].value = _to_float(
            wealth_market_value_individual_offline_change_10k
        )
        worksheet_detail[f"L{row_num}"].value = account_num_new_organization_online
        worksheet_detail[f"M{row_num}"].value = account_num_new_organization_offline

        row_num += 1

    # 5. 每日数据-分渠道开户
    row_num = 38
    for row in ads_hook.get_records(sql_detail_channel.format(p_rpt_date=p_rpt_date)):
        (
            stats_date,
            account_num_new_individual_ths,
            account_num_new_individual_other,
        ) = row

        stats_date = _to_date(stats_date)
        stats_date_num = openpyxl.utils.datetime.to_excel(stats_date)

        worksheet_detail[f"O{row_num}"].value = stats_date_num
        worksheet_detail[f"P{row_num}"].value = account_num_new_individual_ths
        worksheet_detail[f"Q{row_num}"].value = account_num_new_individual_other

        row_num += 1

    workbook.active = worksheet_summary_daily
    workbook.save(result_file_path)


def _change_type_str(change_type):
    if change_type == -1:
        return "，占比明显下降"
    elif change_type == 1:
        return "，占比明显上升"
    else:
        return ""


def _to_date(val):
    if isinstance(val, str):
        return datetime.strptime(val, "%Y-%m-%d").date()
    return val


def _to_float(val, divisor=1.0):
    if val is None:
        return None
    return round(float(val) / divisor, 2)


def generate_major_biz_metric_report(p_begin_date, p_end_date, result_file_path):
    """生成主要经营指标结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/major_biz_metric/major_biz_metric_template.xlsx",
    )

    sql_metric = get_file_content("sql/ads/major_biz_metric/major_biz_metric.sql")

    date_fmt = "%Y-%m-%d"
    p_begin_date = p_begin_date.strftime(date_fmt)
    p_end_date = p_end_date.strftime(date_fmt)

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)

    for worksheet_name in ("全部", "F007"):
        worksheet = workbook[worksheet_name]

        p_ae_code = "" if worksheet_name == "全部" else worksheet_name

        (
            acc_open_online,
            acc_open_offline,
            new_open_online,
            new_open_offline,
            acc_open_indi,
            acc_open_org,
            new_open_indi,
            new_open_org,
            acc_open_ordi,
            acc_open_pi,
            new_open_ordi,
            new_open_pi,
            acc_paying_online,
            acc_paying_offline,
            new_paying_online,
            new_paying_offline,
            acc_paying_indi,
            acc_paying_org,
            new_paying_indi,
            new_paying_org,
            acc_paying_ordi,
            acc_paying_pi,
            new_paying_ordi,
            new_paying_pi,
            acc_valid_online,
            acc_valid_offline,
            new_valid_online,
            new_valid_offline,
            acc_valid_indi,
            acc_valid_org,
            new_valid_indi,
            new_valid_org,
            acc_valid_ordi,
            acc_valid_pi,
            new_valid_ordi,
            new_valid_pi,
            aum_online,
            aum_offline,
            aum_indi,
            aum_org,
            aum_ordi,
            aum_pi,
            commission_online,
            commission_offline,
            commission_indi,
            commission_org,
            commission_ordi,
            commission_pi,
            interest_online,
            interest_offline,
            interest_indi,
            interest_org,
            interest_ordi,
            interest_pi,
            ipo_revenue_online,
            ipo_revenue_offline,
            ipo_revenue_indi,
            ipo_revenue_org,
            ipo_revenue_ordi,
            ipo_revenue_pi,
        ) = ads_hook.get_first(
            sql_metric.format(
                p_begin_date=p_begin_date, p_end_date=p_end_date, p_ae_code=p_ae_code
            )
        )

        worksheet["A1"].value = f"{p_begin_date} ~ {p_end_date}"

        worksheet["D3"].value = acc_open_online
        worksheet["E3"].value = acc_open_offline
        worksheet["D4"].value = new_open_online
        worksheet["E4"].value = new_open_offline
        worksheet["F3"].value = acc_open_indi
        worksheet["G3"].value = acc_open_org
        worksheet["F4"].value = new_open_indi
        worksheet["G4"].value = new_open_org
        worksheet["H3"].value = acc_open_ordi
        worksheet["I3"].value = acc_open_pi
        worksheet["H4"].value = new_open_ordi
        worksheet["I4"].value = new_open_pi

        worksheet["D5"].value = acc_paying_online
        worksheet["E5"].value = acc_paying_offline
        worksheet["D6"].value = new_paying_online
        worksheet["E6"].value = new_paying_offline
        worksheet["F5"].value = acc_paying_indi
        worksheet["G5"].value = acc_paying_org
        worksheet["F6"].value = new_paying_indi
        worksheet["G6"].value = new_paying_org
        worksheet["H5"].value = acc_paying_ordi
        worksheet["I5"].value = acc_paying_pi
        worksheet["H6"].value = new_paying_ordi
        worksheet["I6"].value = new_paying_pi

        worksheet["D7"].value = acc_valid_online
        worksheet["E7"].value = acc_valid_offline
        worksheet["D8"].value = new_valid_online
        worksheet["E8"].value = new_valid_offline
        worksheet["F7"].value = acc_valid_indi
        worksheet["G7"].value = acc_valid_org
        worksheet["F8"].value = new_valid_indi
        worksheet["G8"].value = new_valid_org
        worksheet["H7"].value = acc_valid_ordi
        worksheet["I7"].value = acc_valid_pi
        worksheet["H8"].value = new_valid_ordi
        worksheet["I8"].value = new_valid_pi

        worksheet["D9"].value = _to_float(aum_online)
        worksheet["E9"].value = _to_float(aum_offline)
        worksheet["F9"].value = _to_float(aum_indi)
        worksheet["G9"].value = _to_float(aum_org)
        worksheet["H9"].value = _to_float(aum_ordi)
        worksheet["I9"].value = _to_float(aum_pi)

        worksheet["D10"].value = _to_float(commission_online)
        worksheet["E10"].value = _to_float(commission_offline)
        worksheet["F10"].value = _to_float(commission_indi)
        worksheet["G10"].value = _to_float(commission_org)
        worksheet["H10"].value = _to_float(commission_ordi)
        worksheet["I10"].value = _to_float(commission_pi)

        worksheet["D11"].value = _to_float(interest_online)
        worksheet["E11"].value = _to_float(interest_offline)
        worksheet["F11"].value = _to_float(interest_indi)
        worksheet["G11"].value = _to_float(interest_org)
        worksheet["H11"].value = _to_float(interest_ordi)
        worksheet["I11"].value = _to_float(interest_pi)

        worksheet["D12"].value = _to_float(ipo_revenue_online)
        worksheet["E12"].value = _to_float(ipo_revenue_offline)
        worksheet["F12"].value = _to_float(ipo_revenue_indi)
        worksheet["G12"].value = _to_float(ipo_revenue_org)
        worksheet["H12"].value = _to_float(ipo_revenue_ordi)
        worksheet["I12"].value = _to_float(ipo_revenue_pi)

    workbook.active = workbook["全部"]
    workbook.save(result_file_path)


def generate_major_biz_metric_trend(
    p_begin_year: int, p_end_year: int, result_file_path: str
) -> None:
    """生成主要业务指标趋势结果Excel文件"""

    p_mid_year = p_end_year - 1

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/major_biz_metric/major_biz_metric_trend_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet_name = "Data"
    worksheet = workbook[worksheet_name]

    month_to_column = {
        1: "D",
        2: "E",
        3: "F",
        4: "G",
        5: "H",
        6: "I",
        7: "J",
        8: "K",
        9: "L",
        10: "M",
        11: "N",
        12: "O",
    }
    cat_year_to_row = {
        ("线上-同花顺", p_end_year): 2,
        ("线上-同花顺", p_mid_year): 3,
        ("线上-同花顺", p_begin_year): 4,
        ("线上-星财富", p_end_year): 5,
        ("线上-星财富", p_mid_year): 6,
        ("线上-星财富", p_begin_year): 7,
        ("线下", p_end_year): 8,
        ("线下", p_mid_year): 9,
        ("线下", p_begin_year): 10,
        ("合计", p_end_year): 11,
        ("合计", p_mid_year): 12,
        ("合计", p_begin_year): 13,
    }

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    metric_configs = [
        (
            "注册-新进",
            "sql/ads/major_biz_metric/major_biz_metric_trend_register_new.sql",
            "",
            0,
        ),
        (
            "注册-累计",
            "sql/ads/major_biz_metric/major_biz_metric_trend_register_acc.sql",
            "",
            12,
        ),
        (
            "开户-新进",
            "sql/ads/major_biz_metric/major_biz_metric_trend_open_new.sql",
            "",
            24,
        ),
        (
            "开户-累计",
            "sql/ads/major_biz_metric/major_biz_metric_trend_open_acc.sql",
            "",
            36,
        ),
        (
            "活跃用户数-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_active_user_num_cur.sql",
            "",
            48,
        ),
        (
            "首次入金户数-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_first_deposit_num_cur.sql",
            "",
            60,
        ),
        (
            "首次入金金额-当期平均",
            "sql/ads/major_biz_metric/major_biz_metric_trend_first_deposit_amount_cur.sql",
            "",
            72,
        ),
        (
            "入金户数-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_deposit_num_cur.sql",
            "",
            84,
        ),
        (
            "入金户数-累计",
            "sql/ads/major_biz_metric/major_biz_metric_trend_deposit_num_acc.sql",
            "",
            96,
        ),
        (
            "交易户数-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_num_cur.sql",
            "",
            108,
        ),
        (
            "交易户数-累计",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_num_acc.sql",
            "",
            120,
        ),
        (
            "订单数-美股-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_times_cur.sql",
            "m.biz_line_key like 'BROKER|US%'",
            132,
        ),
        (
            "订单数-港股-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_times_cur.sql",
            "m.biz_line_key like 'BROKER|HKEX%'",
            144,
        ),
        (
            "订单数-A股-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_times_cur.sql",
            "m.biz_line_key like 'BROKER|CN%'",
            156,
        ),
        (
            "订单数-汇总-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_times_cur.sql",
            "(m.biz_line_key like 'BROKER|US%' or m.biz_line_key like 'BROKER|HKEX%' or m.biz_line_key like 'BROKER|CN%')",
            168,
        ),
        (
            "交易量-美股-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_amount_cur.sql",
            "m.biz_line_key like 'BROKER|US%'",
            180,
        ),
        (
            "交易量-港股-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_amount_cur.sql",
            "m.biz_line_key like 'BROKER|HKEX%'",
            192,
        ),
        (
            "交易量-A股-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_amount_cur.sql",
            "m.biz_line_key like 'BROKER|CN%'",
            204,
        ),
        (
            "交易量-汇总-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_amount_cur.sql",
            "(m.biz_line_key like 'BROKER|US%' or m.biz_line_key like 'BROKER|HKEX%' or m.biz_line_key like 'BROKER|CN%')",
            216,
        ),
        (
            "佣金收入-美股-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_commission_cur.sql",
            "m.biz_line_key like 'BROKER|US%'",
            228,
        ),
        (
            "佣金收入-港股-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_commission_cur.sql",
            "m.biz_line_key like 'BROKER|HKEX%'",
            240,
        ),
        (
            "佣金收入-A股-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_commission_cur.sql",
            "m.biz_line_key like 'BROKER|CN%'",
            252,
        ),
        (
            "佣金收入-汇总-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_trade_commission_cur.sql",
            "(m.biz_line_key like 'BROKER|US%' or m.biz_line_key like 'BROKER|HKEX%' or m.biz_line_key like 'BROKER|CN%')",
            264,
        ),
        (
            "利息收入-美股-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_interest_cur.sql",
            "r.currency_code='USD'",
            276,
        ),
        (
            "利息收入-港股-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_interest_cur.sql",
            "r.currency_code='HKD'",
            288,
        ),
        (
            "利息收入-A股-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_interest_cur.sql",
            "r.currency_code='CNY'",
            300,
        ),
        (
            "利息收入-汇总-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_interest_cur.sql",
            "r.currency_code in ('USD','HKD','CNY')",
            312,
        ),
        (
            "IPO收入-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_ipo_cur.sql",
            "",
            324,
        ),
        (
            "票据收入-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_wealth_cur.sql",
            "biz_line_key like 'WEALTH|STPD%'",
            336,
        ),
        (
            "债券收入-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_wealth_cur.sql",
            "biz_line_key like 'WEALTH|OTCB%'",
            348,
        ),
        (
            "现金理财收入-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_wealth_cur.sql",
            "biz_line_key like 'WEALTH|FUND|%MMF%'",
            360,
        ),
        (
            "公募基金收入-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_wealth_cur.sql",
            "biz_line_key like 'WEALTH|FUND|PUBLIC%' and biz_line_key not like 'WEALTH|FUND|%MMF%'",
            372,
        ),
        (
            "私募基金收入-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_wealth_cur.sql",
            "biz_line_key like 'WEALTH|FUND|PRIVATE%'",
            384,
        ),
        (
            "保险收入-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_wealth_cur.sql",
            "biz_line_key like 'WEALTH|INSURANCE%'",
            396,
        ),
        (
            "旅居收入-当期",
            "sql/ads/major_biz_metric/major_biz_metric_trend_wealth_cur.sql",
            "biz_line_key like 'OTHER|IMMIGRATION%'",
            408,
        ),
    ]

    sparkline_location = []
    sparkline_source = []
    for metric_name, sql_path, condition, row_offset in metric_configs:
        sql_query = get_file_content(sql_path)
        sql_query = sql_query.format(
            p_begin_year=p_begin_year, p_end_year=p_end_year, condition=condition
        )

        for cur_month, cat, cur_val, ytd_val in ads_hook.get_records(sql_query):
            cur_year = cur_month // 100
            row = cat_year_to_row[(cat, cur_year)] + row_offset

            worksheet[f"C{row}"].value = cur_year

            cur_month = cur_month % 100
            column = month_to_column[cur_month]
            worksheet[f"{column}{row}"].value = cur_val
            if cur_month == 12:
                worksheet[f"P{row}"].value = ytd_val
                sparkline_location.append(f"Q{row}")
                sparkline_source.append(f"{worksheet_name}!D{row}:O{row}")

    workbook.save(result_file_path)

    excel_sparkline = os.path.join(
        airflow.configuration.get_airflow_home(), "dags/utils/excel_sparkline"
    )
    sparkline_location = ",".join(sparkline_location)
    sparkline_source = ",".join(sparkline_source)

    os.system(
        f'{excel_sparkline} "{result_file_path}" "{worksheet_name}" "{sparkline_location}" "{sparkline_source}"'
    )


def generate_key_biz_metric_trend(p_report_date: date, result_file_path: str) -> None:
    """生成关键指标趋势结果Excel文件"""
    worksheet_name_to_category = {
        "全部": 1,
        "线上-同花顺": 2,
        "线上-星财富": 3,
        "线下(含员工)": 4,
    }

    column_to_config = {
        "C": (  # 累计
            "累计（总数）",
            date(1900, 1, 1),
            p_report_date,
        ),
        "D": (  # T-2年
            f"{p_report_date.year - 2}年",
            date(p_report_date.year - 2, 1, 1),
            date(p_report_date.year - 2, 12, 31),
        ),
        "E": (  # T-1年
            f"{p_report_date.year - 1}年",
            date(p_report_date.year - 1, 1, 1),
            date(p_report_date.year - 1, 12, 31),
        ),
    }

    tmp_date = date(
        p_report_date.year - 1,
        p_report_date.month,
        calendar.monthrange(p_report_date.year - 1, p_report_date.month)[1],
    )
    column_to_config["F"] = (  # 去年同期
        f"去年同期({p_report_date.year - 1}.1~{p_report_date.year - 1}.{p_report_date.month})",
        date(p_report_date.year - 1, 1, 1),
        tmp_date,
    )

    column_to_config["G"] = (  # 本年
        f"{p_report_date.year}.1~{p_report_date.year}.{p_report_date.month}",
        date(p_report_date.year, 1, 1),
        p_report_date,
    )

    match p_report_date.month:
        case 1:
            tmp_year = p_report_date.year - 1
            tmp_month = 10
        case 2:
            tmp_year = p_report_date.year - 1
            tmp_month = 11
        case 3:
            tmp_year = p_report_date.year - 1
            tmp_month = 12
        case _:
            tmp_year = p_report_date.year
            tmp_month = p_report_date.month - 3
    tmp_date = date(tmp_year, tmp_month, calendar.monthrange(tmp_year, tmp_month)[1])
    column_to_config["H"] = (  # T-3月
        f"{tmp_year}年{tmp_month}月",
        date(tmp_year, tmp_month, 1),
        tmp_date,
    )

    match p_report_date.month:
        case 1:
            tmp_year = p_report_date.year - 1
            tmp_month = 11
        case 2:
            tmp_year = p_report_date.year - 1
            tmp_month = 12
        case _:
            tmp_year = p_report_date.year
            tmp_month = p_report_date.month - 2
    tmp_date = date(tmp_year, tmp_month, calendar.monthrange(tmp_year, tmp_month)[1])
    column_to_config["I"] = (  # T-2月
        f"{tmp_year}年{tmp_month}月",
        date(tmp_year, tmp_month, 1),
        tmp_date,
    )

    match p_report_date.month:
        case 1:
            tmp_year = p_report_date.year - 1
            tmp_month = 12
        case _:
            tmp_year = p_report_date.year
            tmp_month = p_report_date.month - 1
    tmp_date = date(tmp_year, tmp_month, calendar.monthrange(tmp_year, tmp_month)[1])
    column_to_config["J"] = (  # T-1月
        f"{tmp_year}年{tmp_month}月",
        date(tmp_year, tmp_month, 1),
        tmp_date,
    )

    column_to_config["K"] = (  # T月
        f"{p_report_date.year}年{p_report_date.month}月",
        date(p_report_date.year, p_report_date.month, 1),
        p_report_date,
    )

    this_week_begin_date = p_report_date - timedelta(p_report_date.weekday())

    tmp_date = this_week_begin_date - timedelta(days=7 * 4)
    column_to_config["L"] = (  # T-4周
        "T-4周",
        tmp_date,
        tmp_date + timedelta(days=6),
    )

    tmp_date = this_week_begin_date - timedelta(days=7 * 3)
    column_to_config["M"] = (  # T-3周
        "T-3周",
        tmp_date,
        tmp_date + timedelta(days=6),
    )

    tmp_date = this_week_begin_date - timedelta(days=7 * 2)
    column_to_config["N"] = (  # T-2周
        "T-2周",
        tmp_date,
        tmp_date + timedelta(days=6),
    )

    tmp_date = this_week_begin_date - timedelta(days=7 * 1)
    column_to_config["O"] = (  # T-3周
        "T-1周",
        tmp_date,
        tmp_date + timedelta(days=6),
    )

    column_to_config["P"] = (  # 本周
        "本周",
        this_week_begin_date,
        p_report_date,
    )

    date_fmt = "%Y-%m-%d"
    tmp_column_index = openpyxl.utils.column_index_from_string("Q")
    for i in range(0, 90):
        tmp_column = openpyxl.utils.get_column_letter(tmp_column_index + i)
        tmp_date = p_report_date - timedelta(days=89 - i)

        column_to_config[tmp_column] = (tmp_date.strftime(date_fmt), tmp_date, tmp_date)

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/major_biz_metric/key_biz_metric_trend_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")
    sql_query = get_file_content("sql/ads/major_biz_metric/key_biz_metric_trend.sql")

    for worksheet_name, p_category in worksheet_name_to_category.items():
        worksheet = workbook[worksheet_name]

        for column, (column_name, begin_date, end_date) in column_to_config.items():
            (
                reg_num,
                reg_num_avg,
                open_num,
                open_num_avg,
                valid_num,
                valid_num_avg,
                deposit_num,
                deposit_num_avg,
                withdraw_num,
                withdraw_num_avg,
                deposit_amount,
                deposit_amount_avg,
                withdraw_amount,
                withdraw_amount_avg,
                net_movement_amount,
                net_movement_amount_avg,
                trade_num,
                trade_num_avg,
                loss_num,
                loss_num_avg,
                active_num_ths,
                active_num_ths_avg,
                active_duration_ths_avg,
                active_num_xcf,
                active_num_xcf_avg,
                active_num_xcf_ths,
                active_num_xcf_ths_avg,
                active_duration_xcf_avg,
                active_duration_xcf_ths_avg,
                active_duration_avg,
                trade_times_all,
                trade_times_all_avg,
                trade_times_hk,
                trade_times_hk_avg,
                trade_times_us,
                trade_times_us_avg,
                trade_times_cn,
                trade_times_cn_avg,
                trade_amount_all,
                trade_amount_all_avg,
                trade_amount_hk,
                trade_amount_hk_avg,
                trade_amount_us,
                trade_amount_us_avg,
                trade_amount_cn,
                trade_amount_cn_avg,
                revenue,
                revenue_avg,
                stock_revenue,
                stock_revenue_avg,
                commission_hk,
                commission_hk_avg,
                commission_us,
                commission_us_avg,
                commission_cn,
                commission_cn_avg,
                ipo_hk,
                ipo_hk_avg,
                ipo_us,
                ipo_us_avg,
                ipo_cn,
                ipo_cn_avg,
                interest_hk,
                interest_hk_avg,
                interest_us,
                interest_us_avg,
                interest_cn,
                interest_cn_avg,
                other_revenue,
                other_revenue_avg,
                asset,
                asset_avg,
                debit_principal,
                debit_principal_avg,
            ) = ads_hook.get_first(
                sql_query.format(
                    p_begin_date=begin_date.strftime(date_fmt),
                    p_end_date=end_date.strftime(date_fmt),
                    p_category=p_category,
                )
            )

            if column == "C":
                worksheet[f"{column}1"].value = column_name
                worksheet[f"{column}2"].value = _to_float(reg_num)
                worksheet[f"{column}3"].value = _to_float(open_num)
                worksheet[f"{column}4"].value = _to_float(deposit_num)
                worksheet[f"{column}5"].value = _to_float(trade_num)
                worksheet[f"{column}6"].value = _to_float(loss_num)
                worksheet[f"{column}9"].value = _to_float(active_num_ths)
                worksheet[f"{column}10"].value = _to_float(active_num_xcf)
                worksheet[f"{column}11"].value = _to_float(active_num_xcf_ths)
                worksheet[f"{column}13"].value = _to_float(trade_times_all)
                worksheet[f"{column}14"].value = _to_float(trade_times_us)
                worksheet[f"{column}15"].value = _to_float(trade_times_hk)
                worksheet[f"{column}16"].value = _to_float(trade_times_cn)
                worksheet[f"{column}17"].value = _to_float(trade_amount_all, 1e6)
                worksheet[f"{column}18"].value = _to_float(trade_amount_us, 1e6)
                worksheet[f"{column}19"].value = _to_float(trade_amount_hk, 1e6)
                worksheet[f"{column}20"].value = _to_float(trade_amount_cn, 1e6)
                worksheet[f"{column}21"].value = _to_float(stock_revenue, 1e3)
                worksheet[f"{column}22"].value = _to_float(commission_us, 1e3)
                worksheet[f"{column}23"].value = _to_float(interest_us, 1e3)
                worksheet[f"{column}24"].value = _to_float(ipo_us, 1e3)
                worksheet[f"{column}25"].value = _to_float(commission_hk, 1e3)
                worksheet[f"{column}26"].value = _to_float(interest_hk, 1e3)
                worksheet[f"{column}27"].value = _to_float(ipo_hk, 1e3)
                worksheet[f"{column}28"].value = _to_float(commission_cn, 1e3)
                worksheet[f"{column}29"].value = _to_float(interest_cn, 1e3)
                worksheet[f"{column}31"].value = _to_float(asset, 1e6)
                worksheet[f"{column}32"].value = _to_float(debit_principal, 1e6)
            else:
                worksheet[f"{column}1"].value = column_name
                worksheet[f"{column}2"].value = _to_float(reg_num_avg)
                worksheet[f"{column}3"].value = _to_float(open_num_avg)
                worksheet[f"{column}4"].value = _to_float(deposit_num_avg)
                worksheet[f"{column}5"].value = _to_float(trade_num_avg)
                worksheet[f"{column}6"].value = _to_float(loss_num_avg)
                worksheet[f"{column}9"].value = _to_float(active_num_ths_avg)
                worksheet[f"{column}10"].value = _to_float(active_num_xcf_avg)
                worksheet[f"{column}11"].value = _to_float(active_num_xcf_ths_avg)
                worksheet[f"{column}13"].value = _to_float(trade_times_all_avg)
                worksheet[f"{column}14"].value = _to_float(trade_times_us_avg)
                worksheet[f"{column}15"].value = _to_float(trade_times_hk_avg)
                worksheet[f"{column}16"].value = _to_float(trade_times_cn_avg)
                worksheet[f"{column}17"].value = _to_float(trade_amount_all_avg, 1e6)
                worksheet[f"{column}18"].value = _to_float(trade_amount_us_avg, 1e6)
                worksheet[f"{column}19"].value = _to_float(trade_amount_hk_avg, 1e6)
                worksheet[f"{column}20"].value = _to_float(trade_amount_cn_avg, 1e6)
                worksheet[f"{column}21"].value = _to_float(stock_revenue_avg, 1e3)
                worksheet[f"{column}22"].value = _to_float(commission_us_avg, 1e3)
                worksheet[f"{column}23"].value = _to_float(interest_us_avg, 1e3)
                worksheet[f"{column}24"].value = _to_float(ipo_us_avg, 1e3)
                worksheet[f"{column}25"].value = _to_float(commission_hk_avg, 1e3)
                worksheet[f"{column}26"].value = _to_float(interest_hk_avg, 1e3)
                worksheet[f"{column}27"].value = _to_float(ipo_hk_avg, 1e3)
                worksheet[f"{column}28"].value = _to_float(commission_cn_avg, 1e3)
                worksheet[f"{column}29"].value = _to_float(interest_cn_avg, 1e3)
                worksheet[f"{column}31"].value = _to_float(asset_avg, 1e6)
                worksheet[f"{column}32"].value = _to_float(debit_principal_avg, 1e6)

    workbook.save(result_file_path)


def generate_wealth_offline_report(p_rpt_date, result_file_path):
    """生成财富管理线下团队业绩报表结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/wealth_offline_report_template.xlsx",
    )
    sql_metric = get_file_content("sql/ads/wealth_report/wealth_offline_report.sql")

    date_fmt_title = "%Y.%m.%d"
    date_fmt_param = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)

    # 1. 财富中心数据
    worksheet = workbook["财富中心数据"]

    for period in ("W", "M"):
        if period == "W":
            (
                cur_begin_date,
                cur_end_date,
                pre_begin_date,
                pre_end_date,
                pre_corresponding_end_date,
            ) = _wealth_offline_weekly_dates(p_rpt_date)
            base_row = 2
        else:
            (
                cur_begin_date,
                cur_end_date,
                pre_begin_date,
                pre_end_date,
                pre_corresponding_end_date,
            ) = _wealth_offline_monthly_dates(p_rpt_date)
            base_row = 15

        title = f"{cur_begin_date.strftime(date_fmt_title)}~{cur_end_date.strftime(date_fmt_title)}"

        (
            all_cur_acc_open,
            all_cur_acc_valid,
            all_cur_acc_pi,
            exclude_fosun_group_all_cur_acc_asset_hkd,
            exclude_fosun_group_all_cur_acc_net_movement_hkd,
            all_cur_acc_asset_hkd,
            all_cur_acc_net_movement_hkd,
            all_cur_acc_commission_hkd,
            all_cur_acc_commission_after_deduct_hkd,
            all_cur_acc_interest_hkd,
            all_cur_acc_wealth_sales_usd,
            all_cur_acc_wealth_revenue_usd,
            all_cur_acc_revenue_hkd,
            all_pre_acc_open,
            all_pre_acc_valid,
            all_pre_acc_pi,
            exclude_fosun_group_all_pre_acc_asset_hkd,
            exclude_fosun_group_all_pre_acc_net_movement_hkd,
            all_pre_acc_asset_hkd,
            all_pre_acc_net_movement_hkd,
            all_pre_acc_commission_hkd,
            all_pre_acc_commission_after_deduct_hkd,
            all_pre_acc_interest_hkd,
            all_pre_acc_wealth_sales_usd,
            all_pre_acc_wealth_revenue_usd,
            all_pre_acc_revenue_hkd,
            all_cur_open,
            all_cur_valid,
            all_cur_pi,
            exclude_fosun_group_all_cur_asset_inc_hkd,
            exclude_fosun_group_all_cur_net_movement_hkd,
            all_cur_asset_inc_hkd,
            all_cur_net_movement_hkd,
            all_cur_commission_hkd,
            all_cur_commission_after_deduct_hkd,
            all_cur_interest_hkd,
            all_cur_wealth_sales_usd,
            all_cur_wealth_revenue_usd,
            all_cur_revenue_hkd,
            all_pre_open,
            all_pre_valid,
            all_pre_pi,
            exclude_fosun_group_all_pre_asset_inc_hkd,
            exclude_fosun_group_all_pre_net_movement_hkd,
            all_pre_asset_inc_hkd,
            all_pre_net_movement_hkd,
            all_pre_commission_hkd,
            all_pre_commission_after_deduct_hkd,
            all_pre_interest_hkd,
            all_pre_wealth_sales_usd,
            all_pre_wealth_revenue_usd,
            all_pre_revenue_hkd,
            all_open_change_rate,
            all_valid_change_rate,
            all_pi_change_rate,
            exclude_fosun_group_all_asset_inc_hkd_change_rate,
            exclude_fosun_group_all_net_movement_hkd_change_rate,
            all_asset_inc_hkd_change_rate,
            all_net_movement_hkd_change_rate,
            all_commission_hkd_change_rate,
            all_commission_after_deduct_hkd_change_rate,
            all_interest_hkd_change_rate,
            all_wealth_sales_usd_change_rate,
            all_wealth_revenue_usd_change_rate,
            all_revenue_hkd_change_rate,
            # -----
            hk_cur_acc_open,
            hk_cur_acc_valid,
            hk_cur_acc_pi,
            exclude_fosun_group_hk_cur_acc_asset_hkd,
            exclude_fosun_group_hk_cur_acc_net_movement_hkd,
            hk_cur_acc_asset_hkd,
            hk_cur_acc_net_movement_hkd,
            hk_cur_acc_commission_hkd,
            hk_cur_acc_commission_after_deduct_hkd,
            hk_cur_acc_interest_hkd,
            hk_cur_acc_wealth_sales_usd,
            hk_cur_acc_wealth_revenue_usd,
            hk_cur_acc_revenue_hkd,
            hk_pre_acc_open,
            hk_pre_acc_valid,
            hk_pre_acc_pi,
            exclude_fosun_group_hk_pre_acc_asset_hkd,
            exclude_fosun_group_hk_pre_acc_net_movement_hkd,
            hk_pre_acc_asset_hkd,
            hk_pre_acc_net_movement_hkd,
            hk_pre_acc_commission_hkd,
            hk_pre_acc_commission_after_deduct_hkd,
            hk_pre_acc_interest_hkd,
            hk_pre_acc_wealth_sales_usd,
            hk_pre_acc_wealth_revenue_usd,
            hk_pre_acc_revenue_hkd,
            hk_cur_open,
            hk_cur_valid,
            hk_cur_pi,
            exclude_fosun_group_hk_cur_asset_inc_hkd,
            exclude_fosun_group_hk_cur_net_movement_hkd,
            hk_cur_asset_inc_hkd,
            hk_cur_net_movement_hkd,
            hk_cur_commission_hkd,
            hk_cur_commission_after_deduct_hkd,
            hk_cur_interest_hkd,
            hk_cur_wealth_sales_usd,
            hk_cur_wealth_revenue_usd,
            hk_cur_revenue_hkd,
            hk_pre_open,
            hk_pre_valid,
            hk_pre_pi,
            exclude_fosun_group_hk_pre_asset_inc_hkd,
            exclude_fosun_group_hk_pre_net_movement_hkd,
            hk_pre_asset_inc_hkd,
            hk_pre_net_movement_hkd,
            hk_pre_commission_hkd,
            hk_pre_commission_after_deduct_hkd,
            hk_pre_interest_hkd,
            hk_pre_wealth_sales_usd,
            hk_pre_wealth_revenue_usd,
            hk_pre_revenue_hkd,
            hk_open_change_rate,
            hk_valid_change_rate,
            hk_pi_change_rate,
            exclude_fosun_group_hk_asset_inc_hkd_change_rate,
            exclude_fosun_group_hk_net_movement_hkd_change_rate,
            hk_asset_inc_hkd_change_rate,
            hk_net_movement_hkd_change_rate,
            hk_commission_hkd_change_rate,
            hk_commission_after_deduct_hkd_change_rate,
            hk_interest_hkd_change_rate,
            hk_wealth_sales_usd_change_rate,
            hk_wealth_revenue_usd_change_rate,
            hk_revenue_hkd_change_rate,
            # -----
            bj_cur_acc_open,
            bj_cur_acc_valid,
            bj_cur_acc_pi,
            exclude_fosun_group_bj_cur_acc_asset_hkd,
            exclude_fosun_group_bj_cur_acc_net_movement_hkd,
            bj_cur_acc_asset_hkd,
            bj_cur_acc_net_movement_hkd,
            bj_cur_acc_commission_hkd,
            bj_cur_acc_commission_after_deduct_hkd,
            bj_cur_acc_interest_hkd,
            bj_cur_acc_wealth_sales_usd,
            bj_cur_acc_wealth_revenue_usd,
            bj_cur_acc_revenue_hkd,
            bj_pre_acc_open,
            bj_pre_acc_valid,
            bj_pre_acc_pi,
            exclude_fosun_group_bj_pre_acc_asset_hkd,
            exclude_fosun_group_bj_pre_acc_net_movement_hkd,
            bj_pre_acc_asset_hkd,
            bj_pre_acc_net_movement_hkd,
            bj_pre_acc_commission_hkd,
            bj_pre_acc_commission_after_deduct_hkd,
            bj_pre_acc_interest_hkd,
            bj_pre_acc_wealth_sales_usd,
            bj_pre_acc_wealth_revenue_usd,
            bj_pre_acc_revenue_hkd,
            bj_cur_open,
            bj_cur_valid,
            bj_cur_pi,
            exclude_fosun_group_bj_cur_asset_inc_hkd,
            exclude_fosun_group_bj_cur_net_movement_hkd,
            bj_cur_asset_inc_hkd,
            bj_cur_net_movement_hkd,
            bj_cur_commission_hkd,
            bj_cur_commission_after_deduct_hkd,
            bj_cur_interest_hkd,
            bj_cur_wealth_sales_usd,
            bj_cur_wealth_revenue_usd,
            bj_cur_revenue_hkd,
            bj_pre_open,
            bj_pre_valid,
            bj_pre_pi,
            exclude_fosun_group_bj_pre_asset_inc_hkd,
            exclude_fosun_group_bj_pre_net_movement_hkd,
            bj_pre_asset_inc_hkd,
            bj_pre_net_movement_hkd,
            bj_pre_commission_hkd,
            bj_pre_commission_after_deduct_hkd,
            bj_pre_interest_hkd,
            bj_pre_wealth_sales_usd,
            bj_pre_wealth_revenue_usd,
            bj_pre_revenue_hkd,
            bj_open_change_rate,
            bj_valid_change_rate,
            bj_pi_change_rate,
            exclude_fosun_group_bj_asset_inc_hkd_change_rate,
            exclude_fosun_group_bj_net_movement_hkd_change_rate,
            bj_asset_inc_hkd_change_rate,
            bj_net_movement_hkd_change_rate,
            bj_commission_hkd_change_rate,
            bj_commission_after_deduct_hkd_change_rate,
            bj_interest_hkd_change_rate,
            bj_wealth_sales_usd_change_rate,
            bj_wealth_revenue_usd_change_rate,
            bj_revenue_hkd_change_rate,
            # -----
            sh_cur_acc_open,
            sh_cur_acc_valid,
            sh_cur_acc_pi,
            exclude_fosun_group_sh_cur_acc_asset_hkd,
            exclude_fosun_group_sh_cur_acc_net_movement_hkd,
            sh_cur_acc_asset_hkd,
            sh_cur_acc_net_movement_hkd,
            sh_cur_acc_commission_hkd,
            sh_cur_acc_commission_after_deduct_hkd,
            sh_cur_acc_interest_hkd,
            sh_cur_acc_wealth_sales_usd,
            sh_cur_acc_wealth_revenue_usd,
            sh_cur_acc_revenue_hkd,
            sh_pre_acc_open,
            sh_pre_acc_valid,
            sh_pre_acc_pi,
            exclude_fosun_group_sh_pre_acc_asset_hkd,
            exclude_fosun_group_sh_pre_acc_net_movement_hkd,
            sh_pre_acc_asset_hkd,
            sh_pre_acc_net_movement_hkd,
            sh_pre_acc_commission_hkd,
            sh_pre_acc_commission_after_deduct_hkd,
            sh_pre_acc_interest_hkd,
            sh_pre_acc_wealth_sales_usd,
            sh_pre_acc_wealth_revenue_usd,
            sh_pre_acc_revenue_hkd,
            sh_cur_open,
            sh_cur_valid,
            sh_cur_pi,
            exclude_fosun_group_sh_cur_asset_inc_hkd,
            exclude_fosun_group_sh_cur_net_movement_hkd,
            sh_cur_asset_inc_hkd,
            sh_cur_net_movement_hkd,
            sh_cur_commission_hkd,
            sh_cur_commission_after_deduct_hkd,
            sh_cur_interest_hkd,
            sh_cur_wealth_sales_usd,
            sh_cur_wealth_revenue_usd,
            sh_cur_revenue_hkd,
            sh_pre_open,
            sh_pre_valid,
            sh_pre_pi,
            exclude_fosun_group_sh_pre_asset_inc_hkd,
            exclude_fosun_group_sh_pre_net_movement_hkd,
            sh_pre_asset_inc_hkd,
            sh_pre_net_movement_hkd,
            sh_pre_commission_hkd,
            sh_pre_commission_after_deduct_hkd,
            sh_pre_interest_hkd,
            sh_pre_wealth_sales_usd,
            sh_pre_wealth_revenue_usd,
            sh_pre_revenue_hkd,
            sh_open_change_rate,
            sh_valid_change_rate,
            sh_pi_change_rate,
            exclude_fosun_group_sh_asset_inc_hkd_change_rate,
            exclude_fosun_group_sh_net_movement_hkd_change_rate,
            sh_asset_inc_hkd_change_rate,
            sh_net_movement_hkd_change_rate,
            sh_commission_hkd_change_rate,
            sh_commission_after_deduct_hkd_change_rate,
            sh_interest_hkd_change_rate,
            sh_wealth_sales_usd_change_rate,
            sh_wealth_revenue_usd_change_rate,
            sh_revenue_hkd_change_rate,
            # -----
            sz_cur_acc_open,
            sz_cur_acc_valid,
            sz_cur_acc_pi,
            exclude_fosun_group_sz_cur_acc_asset_hkd,
            exclude_fosun_group_sz_cur_acc_net_movement_hkd,
            sz_cur_acc_asset_hkd,
            sz_cur_acc_net_movement_hkd,
            sz_cur_acc_commission_hkd,
            sz_cur_acc_commission_after_deduct_hkd,
            sz_cur_acc_interest_hkd,
            sz_cur_acc_wealth_sales_usd,
            sz_cur_acc_wealth_revenue_usd,
            sz_cur_acc_revenue_hkd,
            sz_pre_acc_open,
            sz_pre_acc_valid,
            sz_pre_acc_pi,
            exclude_fosun_group_sz_pre_acc_asset_hkd,
            exclude_fosun_group_sz_pre_acc_net_movement_hkd,
            sz_pre_acc_asset_hkd,
            sz_pre_acc_net_movement_hkd,
            sz_pre_acc_commission_hkd,
            sz_pre_acc_commission_after_deduct_hkd,
            sz_pre_acc_interest_hkd,
            sz_pre_acc_wealth_sales_usd,
            sz_pre_acc_wealth_revenue_usd,
            sz_pre_acc_revenue_hkd,
            sz_cur_open,
            sz_cur_valid,
            sz_cur_pi,
            exclude_fosun_group_sz_cur_asset_inc_hkd,
            exclude_fosun_group_sz_cur_net_movement_hkd,
            sz_cur_asset_inc_hkd,
            sz_cur_net_movement_hkd,
            sz_cur_commission_hkd,
            sz_cur_commission_after_deduct_hkd,
            sz_cur_interest_hkd,
            sz_cur_wealth_sales_usd,
            sz_cur_wealth_revenue_usd,
            sz_cur_revenue_hkd,
            sz_pre_open,
            sz_pre_valid,
            sz_pre_pi,
            exclude_fosun_group_sz_pre_asset_inc_hkd,
            exclude_fosun_group_sz_pre_net_movement_hkd,
            sz_pre_asset_inc_hkd,
            sz_pre_net_movement_hkd,
            sz_pre_commission_hkd,
            sz_pre_commission_after_deduct_hkd,
            sz_pre_interest_hkd,
            sz_pre_wealth_sales_usd,
            sz_pre_wealth_revenue_usd,
            sz_pre_revenue_hkd,
            sz_open_change_rate,
            sz_valid_change_rate,
            sz_pi_change_rate,
            exclude_fosun_group_sz_asset_inc_hkd_change_rate,
            exclude_fosun_group_sz_net_movement_hkd_change_rate,
            sz_asset_inc_hkd_change_rate,
            sz_net_movement_hkd_change_rate,
            sz_commission_hkd_change_rate,
            sz_commission_after_deduct_hkd_change_rate,
            sz_interest_hkd_change_rate,
            sz_wealth_sales_usd_change_rate,
            sz_wealth_revenue_usd_change_rate,
            sz_revenue_hkd_change_rate,
            # -----
            cd_cur_acc_open,
            cd_cur_acc_valid,
            cd_cur_acc_pi,
            exclude_fosun_group_cd_cur_acc_asset_hkd,
            exclude_fosun_group_cd_cur_acc_net_movement_hkd,
            cd_cur_acc_asset_hkd,
            cd_cur_acc_net_movement_hkd,
            cd_cur_acc_commission_hkd,
            cd_cur_acc_commission_after_deduct_hkd,
            cd_cur_acc_interest_hkd,
            cd_cur_acc_wealth_sales_usd,
            cd_cur_acc_wealth_revenue_usd,
            cd_cur_acc_revenue_hkd,
            cd_pre_acc_open,
            cd_pre_acc_valid,
            cd_pre_acc_pi,
            exclude_fosun_group_cd_pre_acc_asset_hkd,
            exclude_fosun_group_cd_pre_acc_net_movement_hkd,
            cd_pre_acc_asset_hkd,
            cd_pre_acc_net_movement_hkd,
            cd_pre_acc_commission_hkd,
            cd_pre_acc_commission_after_deduct_hkd,
            cd_pre_acc_interest_hkd,
            cd_pre_acc_wealth_sales_usd,
            cd_pre_acc_wealth_revenue_usd,
            cd_pre_acc_revenue_hkd,
            cd_cur_open,
            cd_cur_valid,
            cd_cur_pi,
            exclude_fosun_group_cd_cur_asset_inc_hkd,
            exclude_fosun_group_cd_cur_net_movement_hkd,
            cd_cur_asset_inc_hkd,
            cd_cur_net_movement_hkd,
            cd_cur_commission_hkd,
            cd_cur_commission_after_deduct_hkd,
            cd_cur_interest_hkd,
            cd_cur_wealth_sales_usd,
            cd_cur_wealth_revenue_usd,
            cd_cur_revenue_hkd,
            cd_pre_open,
            cd_pre_valid,
            cd_pre_pi,
            exclude_fosun_group_cd_pre_asset_inc_hkd,
            exclude_fosun_group_cd_pre_net_movement_hkd,
            cd_pre_asset_inc_hkd,
            cd_pre_net_movement_hkd,
            cd_pre_commission_hkd,
            cd_pre_commission_after_deduct_hkd,
            cd_pre_interest_hkd,
            cd_pre_wealth_sales_usd,
            cd_pre_wealth_revenue_usd,
            cd_pre_revenue_hkd,
            cd_open_change_rate,
            cd_valid_change_rate,
            cd_pi_change_rate,
            exclude_fosun_group_cd_asset_inc_hkd_change_rate,
            exclude_fosun_group_cd_net_movement_hkd_change_rate,
            cd_asset_inc_hkd_change_rate,
            cd_net_movement_hkd_change_rate,
            cd_commission_hkd_change_rate,
            cd_commission_after_deduct_hkd_change_rate,
            cd_interest_hkd_change_rate,
            cd_wealth_sales_usd_change_rate,
            cd_wealth_revenue_usd_change_rate,
            cd_revenue_hkd_change_rate,
            # -----
            sd_cur_acc_open,
            sd_cur_acc_valid,
            sd_cur_acc_pi,
            exclude_fosun_group_sd_cur_acc_asset_hkd,
            exclude_fosun_group_sd_cur_acc_net_movement_hkd,
            sd_cur_acc_asset_hkd,
            sd_cur_acc_net_movement_hkd,
            sd_cur_acc_commission_hkd,
            sd_cur_acc_commission_after_deduct_hkd,
            sd_cur_acc_interest_hkd,
            sd_cur_acc_wealth_sales_usd,
            sd_cur_acc_wealth_revenue_usd,
            sd_cur_acc_revenue_hkd,
            sd_pre_acc_open,
            sd_pre_acc_valid,
            sd_pre_acc_pi,
            exclude_fosun_group_sd_pre_acc_asset_hkd,
            exclude_fosun_group_sd_pre_acc_net_movement_hkd,
            sd_pre_acc_asset_hkd,
            sd_pre_acc_net_movement_hkd,
            sd_pre_acc_commission_hkd,
            sd_pre_acc_commission_after_deduct_hkd,
            sd_pre_acc_interest_hkd,
            sd_pre_acc_wealth_sales_usd,
            sd_pre_acc_wealth_revenue_usd,
            sd_pre_acc_revenue_hkd,
            sd_cur_open,
            sd_cur_valid,
            sd_cur_pi,
            exclude_fosun_group_sd_cur_asset_inc_hkd,
            exclude_fosun_group_sd_cur_net_movement_hkd,
            sd_cur_asset_inc_hkd,
            sd_cur_net_movement_hkd,
            sd_cur_commission_hkd,
            sd_cur_commission_after_deduct_hkd,
            sd_cur_interest_hkd,
            sd_cur_wealth_sales_usd,
            sd_cur_wealth_revenue_usd,
            sd_cur_revenue_hkd,
            sd_pre_open,
            sd_pre_valid,
            sd_pre_pi,
            exclude_fosun_group_sd_pre_asset_inc_hkd,
            exclude_fosun_group_sd_pre_net_movement_hkd,
            sd_pre_asset_inc_hkd,
            sd_pre_net_movement_hkd,
            sd_pre_commission_hkd,
            sd_pre_commission_after_deduct_hkd,
            sd_pre_interest_hkd,
            sd_pre_wealth_sales_usd,
            sd_pre_wealth_revenue_usd,
            sd_pre_revenue_hkd,
            sd_open_change_rate,
            sd_valid_change_rate,
            sd_pi_change_rate,
            exclude_fosun_group_sd_asset_inc_hkd_change_rate,
            exclude_fosun_group_sd_net_movement_hkd_change_rate,
            sd_asset_inc_hkd_change_rate,
            sd_net_movement_hkd_change_rate,
            sd_commission_hkd_change_rate,
            sd_commission_after_deduct_hkd_change_rate,
            sd_interest_hkd_change_rate,
            sd_wealth_sales_usd_change_rate,
            sd_wealth_revenue_usd_change_rate,
            sd_revenue_hkd_change_rate,
            # -----
            mainland_cur_acc_open,
            mainland_cur_acc_valid,
            mainland_cur_acc_pi,
            exclude_fosun_group_mainland_cur_acc_asset_hkd,
            exclude_fosun_group_mainland_cur_acc_net_movement_hkd,
            mainland_cur_acc_asset_hkd,
            mainland_cur_acc_net_movement_hkd,
            mainland_cur_acc_commission_hkd,
            mainland_cur_acc_commission_after_deduct_hkd,
            mainland_cur_acc_interest_hkd,
            mainland_cur_acc_wealth_sales_usd,
            mainland_cur_acc_wealth_revenue_usd,
            mainland_cur_acc_revenue_hkd,
            mainland_pre_acc_open,
            mainland_pre_acc_valid,
            mainland_pre_acc_pi,
            exclude_fosun_group_mainland_mainland_pre_acc_asset_hkd,
            exclude_fosun_group_mainland_mainland_pre_acc_net_movement_hkd,
            mainland_pre_acc_asset_hkd,
            mainland_pre_acc_net_movement_hkd,
            mainland_pre_acc_commission_hkd,
            mainland_pre_acc_commission_after_deduct_hkd,
            mainland_pre_acc_interest_hkd,
            mainland_pre_acc_wealth_sales_usd,
            mainland_pre_acc_wealth_revenue_usd,
            mainland_pre_acc_revenue_hkd,
            mainland_cur_open,
            mainland_cur_valid,
            mainland_cur_pi,
            exclude_fosun_group_mainland_cur_asset_inc_hkd,
            exclude_fosun_group_mainland_cur_net_movement_hkd,
            mainland_cur_asset_inc_hkd,
            mainland_cur_net_movement_hkd,
            mainland_cur_commission_hkd,
            mainland_cur_commission_after_deduct_hkd,
            mainland_cur_interest_hkd,
            mainland_cur_wealth_sales_usd,
            mainland_cur_wealth_revenue_usd,
            mainland_cur_revenue_hkd,
            mainland_pre_open,
            mainland_pre_valid,
            mainland_pre_pi,
            exclude_fosun_group_mainland_pre_asset_inc_hkd,
            exclude_fosun_group_mainland_pre_net_movement_hkd,
            mainland_pre_asset_inc_hkd,
            mainland_pre_net_movement_hkd,
            mainland_pre_commission_hkd,
            mainland_pre_commission_after_deduct_hkd,
            mainland_pre_interest_hkd,
            mainland_pre_wealth_sales_usd,
            mainland_pre_wealth_revenue_usd,
            mainland_pre_revenue_hkd,
            mainland_open_change_rate,
            mainland_valid_change_rate,
            mainland_pi_change_rate,
            exclude_fosun_group_mainland_asset_inc_hkd_change_rate,
            exclude_fosun_group_mainland_net_movement_hkd_change_rate,
            mainland_asset_inc_hkd_change_rate,
            mainland_net_movement_hkd_change_rate,
            mainland_commission_hkd_change_rate,
            mainland_commission_after_deduct_hkd_change_rate,
            mainland_interest_hkd_change_rate,
            mainland_wealth_sales_usd_change_rate,
            mainland_wealth_revenue_usd_change_rate,
            mainland_revenue_hkd_change_rate,
        ) = ads_hook.get_first(
            sql_metric.format(
                p_cur_begin_date=cur_begin_date.strftime(date_fmt_param),
                p_cur_end_date=cur_end_date.strftime(date_fmt_param),
                p_pre_begin_date=pre_begin_date.strftime(date_fmt_param),
                p_pre_end_date=pre_end_date.strftime(date_fmt_param),
                p_pre_corresponding_end_date=pre_corresponding_end_date.strftime(
                    date_fmt_param
                ),
            )
        )

        worksheet[f"A{base_row}"].value = title

        worksheet[f"C{base_row + 1}"].value = all_cur_acc_open
        worksheet[f"C{base_row + 2}"].value = all_cur_acc_valid
        worksheet[f"C{base_row + 3}"].value = all_cur_acc_pi
        worksheet[f"C{base_row + 4}"].value = _to_float(
            exclude_fosun_group_all_cur_acc_asset_hkd
            if period == "M"
            else exclude_fosun_group_all_cur_acc_net_movement_hkd
        )
        worksheet[f"C{base_row + 5}"].value = _to_float(
            all_cur_acc_asset_hkd if period == "M" else all_cur_acc_net_movement_hkd
        )
        worksheet[f"C{base_row + 6}"].value = _to_float(all_cur_acc_commission_hkd)
        worksheet[f"C{base_row + 7}"].value = _to_float(
            all_cur_acc_commission_after_deduct_hkd
        )
        worksheet[f"C{base_row + 8}"].value = _to_float(all_cur_acc_interest_hkd)
        worksheet[f"C{base_row + 9}"].value = _to_float(all_cur_acc_wealth_sales_usd)
        worksheet[f"C{base_row + 10}"].value = _to_float(all_cur_acc_wealth_revenue_usd)
        worksheet[f"C{base_row + 11}"].value = _to_float(all_cur_acc_revenue_hkd)

        worksheet[f"D{base_row + 1}"].value = all_pre_open
        worksheet[f"D{base_row + 2}"].value = all_pre_valid
        worksheet[f"D{base_row + 3}"].value = all_pre_pi
        worksheet[f"D{base_row + 4}"].value = _to_float(
            exclude_fosun_group_all_pre_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_all_pre_net_movement_hkd
        )
        worksheet[f"D{base_row + 5}"].value = _to_float(
            all_pre_asset_inc_hkd if period == "M" else all_pre_net_movement_hkd
        )
        worksheet[f"D{base_row + 6}"].value = _to_float(all_pre_commission_hkd)
        worksheet[f"D{base_row + 7}"].value = _to_float(
            all_pre_commission_after_deduct_hkd
        )
        worksheet[f"D{base_row + 8}"].value = _to_float(all_pre_interest_hkd)
        worksheet[f"D{base_row + 9}"].value = _to_float(all_pre_wealth_sales_usd)
        worksheet[f"D{base_row + 10}"].value = _to_float(all_pre_wealth_revenue_usd)
        worksheet[f"D{base_row + 11}"].value = _to_float(all_pre_revenue_hkd)

        worksheet[f"E{base_row + 1}"].value = all_cur_open
        worksheet[f"E{base_row + 2}"].value = all_cur_valid
        worksheet[f"E{base_row + 3}"].value = all_cur_pi
        worksheet[f"E{base_row + 4}"].value = _to_float(
            exclude_fosun_group_all_cur_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_all_cur_net_movement_hkd
        )
        worksheet[f"E{base_row + 5}"].value = _to_float(
            all_cur_asset_inc_hkd if period == "M" else all_cur_net_movement_hkd
        )
        worksheet[f"E{base_row + 6}"].value = _to_float(all_cur_commission_hkd)
        worksheet[f"E{base_row + 7}"].value = _to_float(
            all_cur_commission_after_deduct_hkd
        )
        worksheet[f"E{base_row + 8}"].value = _to_float(all_cur_interest_hkd)
        worksheet[f"E{base_row + 9}"].value = _to_float(all_cur_wealth_sales_usd)
        worksheet[f"E{base_row + 10}"].value = _to_float(all_cur_wealth_revenue_usd)
        worksheet[f"E{base_row + 11}"].value = _to_float(all_cur_revenue_hkd)

        worksheet[f"F{base_row + 1}"].value = _to_float(all_open_change_rate)
        worksheet[f"F{base_row + 2}"].value = _to_float(all_valid_change_rate)
        worksheet[f"F{base_row + 3}"].value = _to_float(all_pi_change_rate)
        worksheet[f"F{base_row + 4}"].value = _to_float(
            exclude_fosun_group_all_asset_inc_hkd_change_rate
            if period == "M"
            else exclude_fosun_group_all_net_movement_hkd_change_rate
        )
        worksheet[f"F{base_row + 5}"].value = _to_float(
            all_asset_inc_hkd_change_rate
            if period == "M"
            else all_net_movement_hkd_change_rate
        )
        worksheet[f"F{base_row + 6}"].value = _to_float(all_commission_hkd_change_rate)
        worksheet[f"F{base_row + 7}"].value = _to_float(
            all_commission_after_deduct_hkd_change_rate
        )
        worksheet[f"F{base_row + 8}"].value = _to_float(all_interest_hkd_change_rate)
        worksheet[f"F{base_row + 9}"].value = _to_float(
            all_wealth_sales_usd_change_rate
        )
        worksheet[f"F{base_row + 10}"].value = _to_float(
            all_wealth_revenue_usd_change_rate
        )
        worksheet[f"F{base_row + 11}"].value = _to_float(all_revenue_hkd_change_rate)

        worksheet[f"G{base_row + 1}"].value = hk_cur_acc_open
        worksheet[f"G{base_row + 2}"].value = hk_cur_acc_valid
        worksheet[f"G{base_row + 3}"].value = hk_cur_acc_pi
        worksheet[f"G{base_row + 4}"].value = _to_float(
            exclude_fosun_group_hk_cur_acc_asset_hkd
            if period == "M"
            else exclude_fosun_group_hk_cur_acc_net_movement_hkd
        )
        worksheet[f"G{base_row + 5}"].value = _to_float(
            hk_cur_acc_asset_hkd if period == "M" else hk_cur_acc_net_movement_hkd
        )
        worksheet[f"G{base_row + 6}"].value = _to_float(hk_cur_acc_commission_hkd)
        worksheet[f"G{base_row + 7}"].value = _to_float(
            hk_cur_acc_commission_after_deduct_hkd
        )
        worksheet[f"G{base_row + 8}"].value = _to_float(hk_cur_acc_interest_hkd)
        worksheet[f"G{base_row + 9}"].value = _to_float(hk_cur_acc_wealth_sales_usd)
        worksheet[f"G{base_row + 10}"].value = _to_float(hk_cur_acc_wealth_revenue_usd)
        worksheet[f"G{base_row + 11}"].value = _to_float(hk_cur_acc_revenue_hkd)

        worksheet[f"H{base_row + 1}"].value = hk_pre_open
        worksheet[f"H{base_row + 2}"].value = hk_pre_valid
        worksheet[f"H{base_row + 3}"].value = hk_pre_pi
        worksheet[f"H{base_row + 4}"].value = _to_float(
            exclude_fosun_group_hk_pre_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_hk_pre_net_movement_hkd
        )
        worksheet[f"H{base_row + 5}"].value = _to_float(
            hk_pre_asset_inc_hkd if period == "M" else hk_pre_net_movement_hkd
        )
        worksheet[f"H{base_row + 6}"].value = _to_float(hk_pre_commission_hkd)
        worksheet[f"H{base_row + 7}"].value = _to_float(
            hk_pre_commission_after_deduct_hkd
        )
        worksheet[f"H{base_row + 8}"].value = _to_float(hk_pre_interest_hkd)
        worksheet[f"H{base_row + 9}"].value = _to_float(hk_pre_wealth_sales_usd)
        worksheet[f"H{base_row + 10}"].value = _to_float(hk_pre_wealth_revenue_usd)
        worksheet[f"H{base_row + 11}"].value = _to_float(hk_pre_revenue_hkd)

        worksheet[f"I{base_row + 1}"].value = hk_cur_open
        worksheet[f"I{base_row + 2}"].value = hk_cur_valid
        worksheet[f"I{base_row + 3}"].value = hk_cur_pi
        worksheet[f"I{base_row + 4}"].value = _to_float(
            exclude_fosun_group_hk_cur_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_hk_cur_net_movement_hkd
        )
        worksheet[f"I{base_row + 5}"].value = _to_float(
            hk_cur_asset_inc_hkd if period == "M" else hk_cur_net_movement_hkd
        )
        worksheet[f"I{base_row + 6}"].value = _to_float(hk_cur_commission_hkd)
        worksheet[f"I{base_row + 7}"].value = _to_float(
            hk_cur_commission_after_deduct_hkd
        )
        worksheet[f"I{base_row + 8}"].value = _to_float(hk_cur_interest_hkd)
        worksheet[f"I{base_row + 9}"].value = _to_float(hk_cur_wealth_sales_usd)
        worksheet[f"I{base_row + 10}"].value = _to_float(hk_cur_wealth_revenue_usd)
        worksheet[f"I{base_row + 11}"].value = _to_float(hk_cur_revenue_hkd)

        worksheet[f"J{base_row + 1}"].value = _to_float(hk_open_change_rate)
        worksheet[f"J{base_row + 2}"].value = _to_float(hk_valid_change_rate)
        worksheet[f"J{base_row + 3}"].value = _to_float(hk_pi_change_rate)
        worksheet[f"J{base_row + 4}"].value = _to_float(
            exclude_fosun_group_hk_asset_inc_hkd_change_rate
            if period == "M"
            else exclude_fosun_group_hk_net_movement_hkd_change_rate
        )
        worksheet[f"J{base_row + 5}"].value = _to_float(
            hk_asset_inc_hkd_change_rate
            if period == "M"
            else hk_net_movement_hkd_change_rate
        )
        worksheet[f"J{base_row + 6}"].value = _to_float(hk_commission_hkd_change_rate)
        worksheet[f"J{base_row + 7}"].value = _to_float(
            hk_commission_after_deduct_hkd_change_rate
        )
        worksheet[f"J{base_row + 8}"].value = _to_float(hk_interest_hkd_change_rate)
        worksheet[f"J{base_row + 9}"].value = _to_float(hk_wealth_sales_usd_change_rate)
        worksheet[f"J{base_row + 10}"].value = _to_float(
            hk_wealth_revenue_usd_change_rate
        )
        worksheet[f"J{base_row + 11}"].value = _to_float(hk_revenue_hkd_change_rate)

        worksheet[f"K{base_row + 1}"].value = bj_cur_acc_open
        worksheet[f"K{base_row + 2}"].value = bj_cur_acc_valid
        worksheet[f"K{base_row + 3}"].value = bj_cur_acc_pi
        worksheet[f"K{base_row + 4}"].value = _to_float(
            exclude_fosun_group_bj_cur_acc_asset_hkd
            if period == "M"
            else exclude_fosun_group_bj_cur_acc_net_movement_hkd
        )
        worksheet[f"K{base_row + 5}"].value = _to_float(
            bj_cur_acc_asset_hkd if period == "M" else bj_cur_acc_net_movement_hkd
        )
        worksheet[f"K{base_row + 6}"].value = _to_float(bj_cur_acc_commission_hkd)
        worksheet[f"K{base_row + 7}"].value = _to_float(
            bj_cur_acc_commission_after_deduct_hkd
        )
        worksheet[f"K{base_row + 8}"].value = _to_float(bj_cur_acc_interest_hkd)
        worksheet[f"K{base_row + 9}"].value = _to_float(bj_cur_acc_wealth_sales_usd)
        worksheet[f"K{base_row + 10}"].value = _to_float(bj_cur_acc_wealth_revenue_usd)
        worksheet[f"K{base_row + 11}"].value = _to_float(bj_cur_acc_revenue_hkd)

        worksheet[f"L{base_row + 1}"].value = bj_pre_open
        worksheet[f"L{base_row + 2}"].value = bj_pre_valid
        worksheet[f"L{base_row + 3}"].value = bj_pre_pi
        worksheet[f"L{base_row + 4}"].value = _to_float(
            exclude_fosun_group_bj_pre_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_bj_pre_net_movement_hkd
        )
        worksheet[f"L{base_row + 5}"].value = _to_float(
            bj_pre_asset_inc_hkd if period == "M" else bj_pre_net_movement_hkd
        )
        worksheet[f"L{base_row + 6}"].value = _to_float(bj_pre_commission_hkd)
        worksheet[f"L{base_row + 7}"].value = _to_float(
            bj_pre_commission_after_deduct_hkd
        )
        worksheet[f"L{base_row + 8}"].value = _to_float(bj_pre_interest_hkd)
        worksheet[f"L{base_row + 9}"].value = _to_float(bj_pre_wealth_sales_usd)
        worksheet[f"L{base_row + 10}"].value = _to_float(bj_pre_wealth_revenue_usd)
        worksheet[f"L{base_row + 11}"].value = _to_float(bj_pre_revenue_hkd)

        worksheet[f"M{base_row + 1}"].value = bj_cur_open
        worksheet[f"M{base_row + 2}"].value = bj_cur_valid
        worksheet[f"M{base_row + 3}"].value = bj_cur_pi
        worksheet[f"M{base_row + 4}"].value = _to_float(
            exclude_fosun_group_bj_cur_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_bj_cur_net_movement_hkd
        )
        worksheet[f"M{base_row + 5}"].value = _to_float(
            bj_cur_asset_inc_hkd if period == "M" else bj_cur_net_movement_hkd
        )
        worksheet[f"M{base_row + 6}"].value = _to_float(bj_cur_commission_hkd)
        worksheet[f"M{base_row + 7}"].value = _to_float(
            bj_cur_commission_after_deduct_hkd
        )
        worksheet[f"M{base_row + 8}"].value = _to_float(bj_cur_interest_hkd)
        worksheet[f"M{base_row + 9}"].value = _to_float(bj_cur_wealth_sales_usd)
        worksheet[f"M{base_row + 10}"].value = _to_float(bj_cur_wealth_revenue_usd)
        worksheet[f"M{base_row + 11}"].value = _to_float(bj_cur_revenue_hkd)

        worksheet[f"N{base_row + 1}"].value = _to_float(bj_open_change_rate)
        worksheet[f"N{base_row + 2}"].value = _to_float(bj_valid_change_rate)
        worksheet[f"N{base_row + 3}"].value = _to_float(bj_pi_change_rate)
        worksheet[f"N{base_row + 4}"].value = _to_float(
            exclude_fosun_group_bj_asset_inc_hkd_change_rate
            if period == "M"
            else exclude_fosun_group_bj_net_movement_hkd_change_rate
        )
        worksheet[f"N{base_row + 5}"].value = _to_float(
            bj_asset_inc_hkd_change_rate
            if period == "M"
            else bj_net_movement_hkd_change_rate
        )
        worksheet[f"N{base_row + 6}"].value = _to_float(bj_commission_hkd_change_rate)
        worksheet[f"N{base_row + 7}"].value = _to_float(
            bj_commission_after_deduct_hkd_change_rate
        )
        worksheet[f"N{base_row + 8}"].value = _to_float(bj_interest_hkd_change_rate)
        worksheet[f"N{base_row + 9}"].value = _to_float(bj_wealth_sales_usd_change_rate)
        worksheet[f"N{base_row + 10}"].value = _to_float(
            bj_wealth_revenue_usd_change_rate
        )
        worksheet[f"N{base_row + 11}"].value = _to_float(bj_revenue_hkd_change_rate)

        worksheet[f"O{base_row + 1}"].value = sh_cur_acc_open
        worksheet[f"O{base_row + 2}"].value = sh_cur_acc_valid
        worksheet[f"O{base_row + 3}"].value = sh_cur_acc_pi
        worksheet[f"O{base_row + 4}"].value = _to_float(
            exclude_fosun_group_sh_cur_acc_asset_hkd
            if period == "M"
            else exclude_fosun_group_sh_cur_acc_net_movement_hkd
        )
        worksheet[f"O{base_row + 5}"].value = _to_float(
            sh_cur_acc_asset_hkd if period == "M" else sh_cur_acc_net_movement_hkd
        )
        worksheet[f"O{base_row + 6}"].value = _to_float(sh_cur_acc_commission_hkd)
        worksheet[f"O{base_row + 7}"].value = _to_float(
            sh_cur_acc_commission_after_deduct_hkd
        )
        worksheet[f"O{base_row + 8}"].value = _to_float(sh_cur_acc_interest_hkd)
        worksheet[f"O{base_row + 9}"].value = _to_float(sh_cur_acc_wealth_sales_usd)
        worksheet[f"O{base_row + 10}"].value = _to_float(sh_cur_acc_wealth_revenue_usd)
        worksheet[f"O{base_row + 11}"].value = _to_float(sh_cur_acc_revenue_hkd)

        worksheet[f"P{base_row + 1}"].value = sh_pre_open
        worksheet[f"P{base_row + 2}"].value = sh_pre_valid
        worksheet[f"P{base_row + 3}"].value = sh_pre_pi
        worksheet[f"P{base_row + 4}"].value = _to_float(
            exclude_fosun_group_sh_pre_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_sh_pre_net_movement_hkd
        )
        worksheet[f"P{base_row + 5}"].value = _to_float(
            sh_pre_asset_inc_hkd if period == "M" else sh_pre_net_movement_hkd
        )
        worksheet[f"P{base_row + 6}"].value = _to_float(sh_pre_commission_hkd)
        worksheet[f"P{base_row + 7}"].value = _to_float(
            sh_pre_commission_after_deduct_hkd
        )
        worksheet[f"P{base_row + 8}"].value = _to_float(sh_pre_interest_hkd)
        worksheet[f"P{base_row + 9}"].value = _to_float(sh_pre_wealth_sales_usd)
        worksheet[f"P{base_row + 10}"].value = _to_float(sh_pre_wealth_revenue_usd)
        worksheet[f"P{base_row + 11}"].value = _to_float(sh_pre_revenue_hkd)

        worksheet[f"Q{base_row + 1}"].value = sh_cur_open
        worksheet[f"Q{base_row + 2}"].value = sh_cur_valid
        worksheet[f"Q{base_row + 3}"].value = sh_cur_pi
        worksheet[f"Q{base_row + 4}"].value = _to_float(
            exclude_fosun_group_sh_cur_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_sh_cur_net_movement_hkd
        )
        worksheet[f"Q{base_row + 5}"].value = _to_float(
            sh_cur_asset_inc_hkd if period == "M" else sh_cur_net_movement_hkd
        )
        worksheet[f"Q{base_row + 6}"].value = _to_float(sh_cur_commission_hkd)
        worksheet[f"Q{base_row + 7}"].value = _to_float(
            sh_cur_commission_after_deduct_hkd
        )
        worksheet[f"Q{base_row + 8}"].value = _to_float(sh_cur_interest_hkd)
        worksheet[f"Q{base_row + 9}"].value = _to_float(sh_cur_wealth_sales_usd)
        worksheet[f"Q{base_row + 10}"].value = _to_float(sh_cur_wealth_revenue_usd)
        worksheet[f"Q{base_row + 11}"].value = _to_float(sh_cur_revenue_hkd)

        worksheet[f"R{base_row + 1}"].value = _to_float(sh_open_change_rate)
        worksheet[f"R{base_row + 2}"].value = _to_float(sh_valid_change_rate)
        worksheet[f"R{base_row + 3}"].value = _to_float(sh_pi_change_rate)
        worksheet[f"R{base_row + 4}"].value = _to_float(
            exclude_fosun_group_sh_asset_inc_hkd_change_rate
            if period == "M"
            else exclude_fosun_group_sh_net_movement_hkd_change_rate
        )
        worksheet[f"R{base_row + 5}"].value = _to_float(
            sh_asset_inc_hkd_change_rate
            if period == "M"
            else sh_net_movement_hkd_change_rate
        )
        worksheet[f"R{base_row + 6}"].value = _to_float(sh_commission_hkd_change_rate)
        worksheet[f"R{base_row + 7}"].value = _to_float(
            sh_commission_after_deduct_hkd_change_rate
        )
        worksheet[f"R{base_row + 8}"].value = _to_float(sh_interest_hkd_change_rate)
        worksheet[f"R{base_row + 9}"].value = _to_float(sh_wealth_sales_usd_change_rate)
        worksheet[f"R{base_row + 10}"].value = _to_float(
            sh_wealth_revenue_usd_change_rate
        )
        worksheet[f"R{base_row + 11}"].value = _to_float(sh_revenue_hkd_change_rate)

        worksheet[f"S{base_row + 1}"].value = sz_cur_acc_open
        worksheet[f"S{base_row + 2}"].value = sz_cur_acc_valid
        worksheet[f"S{base_row + 3}"].value = sz_cur_acc_pi
        worksheet[f"S{base_row + 4}"].value = _to_float(
            exclude_fosun_group_sz_cur_acc_asset_hkd
            if period == "M"
            else exclude_fosun_group_sz_cur_acc_net_movement_hkd
        )
        worksheet[f"S{base_row + 5}"].value = _to_float(
            sz_cur_acc_asset_hkd if period == "M" else sz_cur_acc_net_movement_hkd
        )
        worksheet[f"S{base_row + 6}"].value = _to_float(sz_cur_acc_commission_hkd)
        worksheet[f"S{base_row + 7}"].value = _to_float(
            sz_cur_acc_commission_after_deduct_hkd
        )
        worksheet[f"S{base_row + 8}"].value = _to_float(sz_cur_acc_interest_hkd)
        worksheet[f"S{base_row + 9}"].value = _to_float(sz_cur_acc_wealth_sales_usd)
        worksheet[f"S{base_row + 10}"].value = _to_float(sz_cur_acc_wealth_revenue_usd)
        worksheet[f"S{base_row + 11}"].value = _to_float(sz_cur_acc_revenue_hkd)

        worksheet[f"T{base_row + 1}"].value = sz_pre_open
        worksheet[f"T{base_row + 2}"].value = sz_pre_valid
        worksheet[f"T{base_row + 3}"].value = sz_pre_pi
        worksheet[f"T{base_row + 4}"].value = _to_float(
            exclude_fosun_group_sz_pre_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_sz_pre_net_movement_hkd
        )
        worksheet[f"T{base_row + 5}"].value = _to_float(
            sz_pre_asset_inc_hkd if period == "M" else sz_pre_net_movement_hkd
        )
        worksheet[f"T{base_row + 6}"].value = _to_float(sz_pre_commission_hkd)
        worksheet[f"T{base_row + 7}"].value = _to_float(
            sz_pre_commission_after_deduct_hkd
        )
        worksheet[f"T{base_row + 8}"].value = _to_float(sz_pre_interest_hkd)
        worksheet[f"T{base_row + 9}"].value = _to_float(sz_pre_wealth_sales_usd)
        worksheet[f"T{base_row + 10}"].value = _to_float(sz_pre_wealth_revenue_usd)
        worksheet[f"T{base_row + 11}"].value = _to_float(sz_pre_revenue_hkd)

        worksheet[f"U{base_row + 1}"].value = sz_cur_open
        worksheet[f"U{base_row + 2}"].value = sz_cur_valid
        worksheet[f"U{base_row + 3}"].value = sz_cur_pi
        worksheet[f"U{base_row + 4}"].value = _to_float(
            exclude_fosun_group_sz_cur_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_sz_cur_net_movement_hkd
        )
        worksheet[f"U{base_row + 5}"].value = _to_float(
            sz_cur_asset_inc_hkd if period == "M" else sz_cur_net_movement_hkd
        )
        worksheet[f"U{base_row + 6}"].value = _to_float(sz_cur_commission_hkd)
        worksheet[f"U{base_row + 7}"].value = _to_float(
            sz_cur_commission_after_deduct_hkd
        )
        worksheet[f"U{base_row + 8}"].value = _to_float(sz_cur_interest_hkd)
        worksheet[f"U{base_row + 9}"].value = _to_float(sz_cur_wealth_sales_usd)
        worksheet[f"U{base_row + 10}"].value = _to_float(sz_cur_wealth_revenue_usd)
        worksheet[f"U{base_row + 11}"].value = _to_float(sz_cur_revenue_hkd)

        worksheet[f"V{base_row + 1}"].value = _to_float(sz_open_change_rate)
        worksheet[f"V{base_row + 2}"].value = _to_float(sz_valid_change_rate)
        worksheet[f"V{base_row + 3}"].value = _to_float(sz_pi_change_rate)
        worksheet[f"V{base_row + 4}"].value = _to_float(
            exclude_fosun_group_sz_asset_inc_hkd_change_rate
            if period == "M"
            else exclude_fosun_group_sz_net_movement_hkd_change_rate
        )
        worksheet[f"V{base_row + 5}"].value = _to_float(
            sz_asset_inc_hkd_change_rate
            if period == "M"
            else sz_net_movement_hkd_change_rate
        )
        worksheet[f"V{base_row + 6}"].value = _to_float(sz_commission_hkd_change_rate)
        worksheet[f"V{base_row + 7}"].value = _to_float(
            sz_commission_after_deduct_hkd_change_rate
        )
        worksheet[f"V{base_row + 8}"].value = _to_float(sz_interest_hkd_change_rate)
        worksheet[f"V{base_row + 9}"].value = _to_float(sz_wealth_sales_usd_change_rate)
        worksheet[f"V{base_row + 10}"].value = _to_float(
            sz_wealth_revenue_usd_change_rate
        )
        worksheet[f"V{base_row + 11}"].value = _to_float(sz_revenue_hkd_change_rate)

        worksheet[f"W{base_row + 1}"].value = cd_cur_acc_open
        worksheet[f"W{base_row + 2}"].value = cd_cur_acc_valid
        worksheet[f"W{base_row + 3}"].value = cd_cur_acc_pi
        worksheet[f"W{base_row + 4}"].value = _to_float(
            exclude_fosun_group_cd_cur_acc_asset_hkd
            if period == "M"
            else exclude_fosun_group_cd_cur_acc_net_movement_hkd
        )
        worksheet[f"W{base_row + 5}"].value = _to_float(
            cd_cur_acc_asset_hkd if period == "M" else cd_cur_acc_net_movement_hkd
        )
        worksheet[f"W{base_row + 6}"].value = _to_float(cd_cur_acc_commission_hkd)
        worksheet[f"W{base_row + 7}"].value = _to_float(
            cd_cur_acc_commission_after_deduct_hkd
        )
        worksheet[f"W{base_row + 8}"].value = _to_float(cd_cur_acc_interest_hkd)
        worksheet[f"W{base_row + 9}"].value = _to_float(cd_cur_acc_wealth_sales_usd)
        worksheet[f"W{base_row + 10}"].value = _to_float(cd_cur_acc_wealth_revenue_usd)
        worksheet[f"W{base_row + 11}"].value = _to_float(cd_cur_acc_revenue_hkd)

        worksheet[f"X{base_row + 1}"].value = cd_pre_open
        worksheet[f"X{base_row + 2}"].value = cd_pre_valid
        worksheet[f"X{base_row + 3}"].value = cd_pre_pi
        worksheet[f"X{base_row + 4}"].value = _to_float(
            exclude_fosun_group_cd_pre_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_cd_pre_net_movement_hkd
        )
        worksheet[f"X{base_row + 5}"].value = _to_float(
            cd_pre_asset_inc_hkd if period == "M" else cd_pre_net_movement_hkd
        )
        worksheet[f"X{base_row + 6}"].value = _to_float(cd_pre_commission_hkd)
        worksheet[f"X{base_row + 7}"].value = _to_float(
            cd_pre_commission_after_deduct_hkd
        )
        worksheet[f"X{base_row + 8}"].value = _to_float(cd_pre_interest_hkd)
        worksheet[f"X{base_row + 9}"].value = _to_float(cd_pre_wealth_sales_usd)
        worksheet[f"X{base_row + 10}"].value = _to_float(cd_pre_wealth_revenue_usd)
        worksheet[f"X{base_row + 11}"].value = _to_float(cd_pre_revenue_hkd)

        worksheet[f"Y{base_row + 1}"].value = cd_cur_open
        worksheet[f"Y{base_row + 2}"].value = cd_cur_valid
        worksheet[f"Y{base_row + 3}"].value = cd_cur_pi
        worksheet[f"Y{base_row + 4}"].value = _to_float(
            exclude_fosun_group_cd_cur_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_cd_cur_net_movement_hkd
        )
        worksheet[f"Y{base_row + 5}"].value = _to_float(
            cd_cur_asset_inc_hkd if period == "M" else cd_cur_net_movement_hkd
        )
        worksheet[f"Y{base_row + 6}"].value = _to_float(cd_cur_commission_hkd)
        worksheet[f"Y{base_row + 7}"].value = _to_float(
            cd_cur_commission_after_deduct_hkd
        )
        worksheet[f"Y{base_row + 8}"].value = _to_float(cd_cur_interest_hkd)
        worksheet[f"Y{base_row + 9}"].value = _to_float(cd_cur_wealth_sales_usd)
        worksheet[f"Y{base_row + 10}"].value = _to_float(cd_cur_wealth_revenue_usd)
        worksheet[f"Y{base_row + 11}"].value = _to_float(cd_cur_revenue_hkd)

        worksheet[f"Z{base_row + 1}"].value = _to_float(cd_open_change_rate)
        worksheet[f"Z{base_row + 2}"].value = _to_float(cd_valid_change_rate)
        worksheet[f"Z{base_row + 3}"].value = _to_float(cd_pi_change_rate)
        worksheet[f"Z{base_row + 4}"].value = _to_float(
            exclude_fosun_group_cd_asset_inc_hkd_change_rate
            if period == "M"
            else exclude_fosun_group_cd_net_movement_hkd_change_rate
        )
        worksheet[f"Z{base_row + 5}"].value = _to_float(
            cd_asset_inc_hkd_change_rate
            if period == "M"
            else cd_net_movement_hkd_change_rate
        )
        worksheet[f"Z{base_row + 6}"].value = _to_float(cd_commission_hkd_change_rate)
        worksheet[f"Z{base_row + 7}"].value = _to_float(
            cd_commission_after_deduct_hkd_change_rate
        )
        worksheet[f"Z{base_row + 8}"].value = _to_float(cd_interest_hkd_change_rate)
        worksheet[f"Z{base_row + 9}"].value = _to_float(cd_wealth_sales_usd_change_rate)
        worksheet[f"Z{base_row + 10}"].value = _to_float(
            cd_wealth_revenue_usd_change_rate
        )
        worksheet[f"Z{base_row + 11}"].value = _to_float(cd_revenue_hkd_change_rate)

        worksheet[f"AA{base_row + 1}"].value = sd_cur_acc_open
        worksheet[f"AA{base_row + 2}"].value = sd_cur_acc_valid
        worksheet[f"AA{base_row + 3}"].value = sd_cur_acc_pi
        worksheet[f"AA{base_row + 4}"].value = _to_float(
            exclude_fosun_group_sd_cur_acc_asset_hkd
            if period == "M"
            else exclude_fosun_group_sd_cur_acc_net_movement_hkd
        )
        worksheet[f"AA{base_row + 5}"].value = _to_float(
            sd_cur_acc_asset_hkd if period == "M" else sd_cur_acc_net_movement_hkd
        )
        worksheet[f"AA{base_row + 6}"].value = _to_float(sd_cur_acc_commission_hkd)
        worksheet[f"AA{base_row + 7}"].value = _to_float(
            sd_cur_acc_commission_after_deduct_hkd
        )
        worksheet[f"AA{base_row + 8}"].value = _to_float(sd_cur_acc_interest_hkd)
        worksheet[f"AA{base_row + 9}"].value = _to_float(sd_cur_acc_wealth_sales_usd)
        worksheet[f"AA{base_row + 10}"].value = _to_float(sd_cur_acc_wealth_revenue_usd)
        worksheet[f"AA{base_row + 11}"].value = _to_float(sd_cur_acc_revenue_hkd)

        worksheet[f"AB{base_row + 1}"].value = sd_pre_open
        worksheet[f"AB{base_row + 2}"].value = sd_pre_valid
        worksheet[f"AB{base_row + 3}"].value = sd_pre_pi
        worksheet[f"AB{base_row + 4}"].value = _to_float(
            exclude_fosun_group_sd_pre_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_sd_pre_net_movement_hkd
        )
        worksheet[f"AB{base_row + 5}"].value = _to_float(
            sd_pre_asset_inc_hkd if period == "M" else sd_pre_net_movement_hkd
        )
        worksheet[f"AB{base_row + 6}"].value = _to_float(sd_pre_commission_hkd)
        worksheet[f"AB{base_row + 7}"].value = _to_float(
            sd_pre_commission_after_deduct_hkd
        )
        worksheet[f"AB{base_row + 8}"].value = _to_float(sd_pre_interest_hkd)
        worksheet[f"AB{base_row + 9}"].value = _to_float(sd_pre_wealth_sales_usd)
        worksheet[f"AB{base_row + 10}"].value = _to_float(sd_pre_wealth_revenue_usd)
        worksheet[f"AB{base_row + 11}"].value = _to_float(sd_pre_revenue_hkd)

        worksheet[f"AC{base_row + 1}"].value = sd_cur_open
        worksheet[f"AC{base_row + 2}"].value = sd_cur_valid
        worksheet[f"AC{base_row + 3}"].value = sd_cur_pi
        worksheet[f"AC{base_row + 4}"].value = _to_float(
            exclude_fosun_group_sd_cur_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_sd_cur_net_movement_hkd
        )
        worksheet[f"AC{base_row + 5}"].value = _to_float(
            sd_cur_asset_inc_hkd if period == "M" else sd_cur_net_movement_hkd
        )
        worksheet[f"AC{base_row + 6}"].value = _to_float(sd_cur_commission_hkd)
        worksheet[f"AC{base_row + 7}"].value = _to_float(
            sd_cur_commission_after_deduct_hkd
        )
        worksheet[f"AC{base_row + 8}"].value = _to_float(sd_cur_interest_hkd)
        worksheet[f"AC{base_row + 9}"].value = _to_float(sd_cur_wealth_sales_usd)
        worksheet[f"AC{base_row + 10}"].value = _to_float(sd_cur_wealth_revenue_usd)
        worksheet[f"AC{base_row + 11}"].value = _to_float(sd_cur_revenue_hkd)

        worksheet[f"AD{base_row + 1}"].value = _to_float(sd_open_change_rate)
        worksheet[f"AD{base_row + 2}"].value = _to_float(sd_valid_change_rate)
        worksheet[f"AD{base_row + 3}"].value = _to_float(sd_pi_change_rate)
        worksheet[f"AD{base_row + 4}"].value = _to_float(
            exclude_fosun_group_sd_asset_inc_hkd_change_rate
            if period == "M"
            else exclude_fosun_group_sd_net_movement_hkd_change_rate
        )
        worksheet[f"AD{base_row + 5}"].value = _to_float(
            sd_asset_inc_hkd_change_rate
            if period == "M"
            else sd_net_movement_hkd_change_rate
        )
        worksheet[f"AD{base_row + 6}"].value = _to_float(sd_commission_hkd_change_rate)
        worksheet[f"AD{base_row + 7}"].value = _to_float(
            sd_commission_after_deduct_hkd_change_rate
        )
        worksheet[f"AD{base_row + 8}"].value = _to_float(sd_interest_hkd_change_rate)
        worksheet[f"AD{base_row + 9}"].value = _to_float(
            sd_wealth_sales_usd_change_rate
        )
        worksheet[f"AD{base_row + 10}"].value = _to_float(
            sd_wealth_revenue_usd_change_rate
        )
        worksheet[f"AD{base_row + 11}"].value = _to_float(sd_revenue_hkd_change_rate)

        worksheet[f"AE{base_row + 1}"].value = mainland_cur_acc_open
        worksheet[f"AE{base_row + 2}"].value = mainland_cur_acc_valid
        worksheet[f"AE{base_row + 3}"].value = mainland_cur_acc_pi
        worksheet[f"AE{base_row + 4}"].value = _to_float(
            exclude_fosun_group_mainland_cur_acc_asset_hkd
            if period == "M"
            else exclude_fosun_group_mainland_cur_acc_net_movement_hkd
        )
        worksheet[f"AE{base_row + 5}"].value = _to_float(
            mainland_cur_acc_asset_hkd
            if period == "M"
            else mainland_cur_acc_net_movement_hkd
        )
        worksheet[f"AE{base_row + 6}"].value = _to_float(
            mainland_cur_acc_commission_hkd
        )
        worksheet[f"AE{base_row + 7}"].value = _to_float(
            mainland_cur_acc_commission_after_deduct_hkd
        )
        worksheet[f"AE{base_row + 8}"].value = _to_float(mainland_cur_acc_interest_hkd)
        worksheet[f"AE{base_row + 9}"].value = _to_float(
            mainland_cur_acc_wealth_sales_usd
        )
        worksheet[f"AE{base_row + 10}"].value = _to_float(
            mainland_cur_acc_wealth_revenue_usd
        )
        worksheet[f"AE{base_row + 11}"].value = _to_float(mainland_cur_acc_revenue_hkd)

        worksheet[f"AF{base_row + 1}"].value = mainland_pre_open
        worksheet[f"AF{base_row + 2}"].value = mainland_pre_valid
        worksheet[f"AF{base_row + 3}"].value = mainland_pre_pi
        worksheet[f"AF{base_row + 4}"].value = _to_float(
            exclude_fosun_group_mainland_pre_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_mainland_pre_net_movement_hkd
        )
        worksheet[f"AF{base_row + 5}"].value = _to_float(
            mainland_pre_asset_inc_hkd
            if period == "M"
            else mainland_pre_net_movement_hkd
        )
        worksheet[f"AF{base_row + 6}"].value = _to_float(mainland_pre_commission_hkd)
        worksheet[f"AF{base_row + 7}"].value = _to_float(
            mainland_pre_commission_after_deduct_hkd
        )
        worksheet[f"AF{base_row + 8}"].value = _to_float(mainland_pre_interest_hkd)
        worksheet[f"AF{base_row + 9}"].value = _to_float(mainland_pre_wealth_sales_usd)
        worksheet[f"AF{base_row + 10}"].value = _to_float(
            mainland_pre_wealth_revenue_usd
        )
        worksheet[f"AF{base_row + 11}"].value = _to_float(mainland_pre_revenue_hkd)

        worksheet[f"AG{base_row + 1}"].value = mainland_cur_open
        worksheet[f"AG{base_row + 2}"].value = mainland_cur_valid
        worksheet[f"AG{base_row + 3}"].value = mainland_cur_pi
        worksheet[f"AG{base_row + 4}"].value = _to_float(
            exclude_fosun_group_mainland_cur_asset_inc_hkd
            if period == "M"
            else exclude_fosun_group_mainland_cur_net_movement_hkd
        )
        worksheet[f"AG{base_row + 5}"].value = _to_float(
            mainland_cur_asset_inc_hkd
            if period == "M"
            else mainland_cur_net_movement_hkd
        )
        worksheet[f"AG{base_row + 6}"].value = _to_float(mainland_cur_commission_hkd)
        worksheet[f"AG{base_row + 7}"].value = _to_float(
            mainland_cur_commission_after_deduct_hkd
        )
        worksheet[f"AG{base_row + 8}"].value = _to_float(mainland_cur_interest_hkd)
        worksheet[f"AG{base_row + 9}"].value = _to_float(mainland_cur_wealth_sales_usd)
        worksheet[f"AG{base_row + 10}"].value = _to_float(
            mainland_cur_wealth_revenue_usd
        )
        worksheet[f"AG{base_row + 11}"].value = _to_float(mainland_cur_revenue_hkd)

        worksheet[f"AH{base_row + 1}"].value = _to_float(mainland_open_change_rate)
        worksheet[f"AH{base_row + 2}"].value = _to_float(mainland_valid_change_rate)
        worksheet[f"AH{base_row + 3}"].value = _to_float(mainland_pi_change_rate)
        worksheet[f"AH{base_row + 4}"].value = _to_float(
            exclude_fosun_group_mainland_asset_inc_hkd_change_rate
            if period == "M"
            else exclude_fosun_group_mainland_net_movement_hkd_change_rate
        )
        worksheet[f"AH{base_row + 5}"].value = _to_float(
            mainland_asset_inc_hkd_change_rate
            if period == "M"
            else mainland_net_movement_hkd_change_rate
        )
        worksheet[f"AH{base_row + 6}"].value = _to_float(
            mainland_commission_hkd_change_rate
        )
        worksheet[f"AH{base_row + 7}"].value = _to_float(
            mainland_commission_after_deduct_hkd_change_rate
        )
        worksheet[f"AH{base_row + 8}"].value = _to_float(
            mainland_interest_hkd_change_rate
        )
        worksheet[f"AH{base_row + 9}"].value = _to_float(
            mainland_wealth_sales_usd_change_rate
        )
        worksheet[f"AH{base_row + 10}"].value = _to_float(
            mainland_wealth_revenue_usd_change_rate
        )
        worksheet[f"AH{base_row + 11}"].value = _to_float(
            mainland_revenue_hkd_change_rate
        )

    for col in ("D", "H", "L", "P", "T", "X", "AB", "AF"):
        worksheet.column_dimensions[col].hidden = True

    # 2. 销售个人业绩明细 / AE个人业绩明细
    detail_worksheets = [
        (1, "销售个人业绩明细"),
        (2, "BD个人业绩明细"),
        (3, "AE个人业绩明细"),
    ]

    center = openpyxl.styles.Alignment(horizontal="center", vertical="center")

    (
        cur_begin_date,
        cur_end_date,
        pre_begin_date,
        pre_end_date,
        pre_corresponding_end_date,
    ) = _wealth_offline_monthly_dates(p_rpt_date)
    cur_end_date = p_rpt_date

    for p_report_type, detail_worksheet_name in detail_worksheets:
        detail_ws = workbook[detail_worksheet_name]
        sql_detail_metric = get_file_content(
            "sql/ads/wealth_report/wealth_offline_detail_report.sql"
        )
        row_num = 2
        for (
            sales_name,
            all_acc_open,
            all_acc_valid,
            all_cur_pi,
            exclude_fosun_group_all_aum_hkd,
            all_aum_hkd,
            all_commission_hkd,
            all_commission_after_deduct_hkd,
            all_interest_hkd,
            all_wealth_revenue_hkd,
            cur_total_revenue_hkd,
            all_deposit_value_hkd,
            cur_acc_wealth_sales_hkd,
        ) in ads_hook.get_records(
            sql_detail_metric.format(
                p_cur_begin_date=cur_begin_date.strftime(date_fmt_param),
                p_cur_end_date=cur_end_date.strftime(date_fmt_param),
                p_pre_begin_date=pre_begin_date.strftime(date_fmt_param),
                p_pre_end_date=pre_end_date.strftime(date_fmt_param),
                p_pre_corresponding_end_date=pre_corresponding_end_date.strftime(
                    date_fmt_param
                ),
                p_report_type=p_report_type,
            )
        ):
            detail_ws[f"A{row_num}"].value = sales_name
            detail_ws[f"A{row_num}"].alignment = center
            detail_ws[f"B{row_num}"].value = all_acc_open
            detail_ws[f"B{row_num}"].alignment = center
            detail_ws[f"C{row_num}"].value = all_acc_valid
            detail_ws[f"C{row_num}"].alignment = center
            detail_ws[f"D{row_num}"].value = all_cur_pi
            detail_ws[f"D{row_num}"].alignment = center
            detail_ws[f"E{row_num}"].value = _to_float(exclude_fosun_group_all_aum_hkd)
            detail_ws[f"E{row_num}"].alignment = center
            detail_ws[f"E{row_num}"].number_format = "[$HKD]\\ #,##0;[$HKD]\\ \\-#,##0"
            detail_ws[f"F{row_num}"].value = _to_float(all_aum_hkd)
            detail_ws[f"F{row_num}"].alignment = center
            detail_ws[f"F{row_num}"].number_format = "[$HKD]\\ #,##0;[$HKD]\\ \\-#,##0"
            detail_ws[f"G{row_num}"].value = _to_float(all_commission_hkd)
            detail_ws[f"G{row_num}"].alignment = center
            detail_ws[f"G{row_num}"].number_format = "[$HKD]\\ #,##0;[$HKD]\\ \\-#,##0"
            detail_ws[f"H{row_num}"].value = _to_float(all_commission_after_deduct_hkd)
            detail_ws[f"H{row_num}"].alignment = center
            detail_ws[f"H{row_num}"].number_format = "[$HKD]\\ #,##0;[$HKD]\\ \\-#,##0"
            detail_ws[f"I{row_num}"].value = _to_float(all_interest_hkd)
            detail_ws[f"I{row_num}"].alignment = center
            detail_ws[f"I{row_num}"].number_format = "[$HKD]\\ #,##0;[$HKD]\\ \\-#,##0"
            detail_ws[f"J{row_num}"].value = _to_float(all_wealth_revenue_hkd)
            detail_ws[f"J{row_num}"].alignment = center
            detail_ws[f"J{row_num}"].number_format = "[$HKD]\\ #,##0;[$HKD]\\ \\-#,##0"
            detail_ws[f"K{row_num}"].value = _to_float(cur_total_revenue_hkd)
            detail_ws[f"K{row_num}"].alignment = center
            detail_ws[f"K{row_num}"].number_format = "[$HKD]\\ #,##0;[$HKD]\\ \\-#,##0"

            if detail_worksheet_name == "BD个人业绩明细":
                detail_ws[f"L{row_num}"].value = _to_float(all_deposit_value_hkd)
                detail_ws[f"L{row_num}"].alignment = center
                detail_ws[
                    f"L{row_num}"
                ].number_format = "[$HKD]\\ #,##0;[$HKD]\\ \\-#,##0"
                detail_ws[f"M{row_num}"].value = _to_float(cur_acc_wealth_sales_hkd)
                detail_ws[f"M{row_num}"].alignment = center
                detail_ws[
                    f"M{row_num}"
                ].number_format = "[$HKD]\\ #,##0;[$HKD]\\ \\-#,##0"

            row_num += 1

    # 3. 写出结果
    workbook.active = worksheet
    workbook.save(result_file_path)


def _wealth_offline_weekly_dates(
    asof_date: date,
) -> tuple[date, date, date, date, date]:
    cur_begin_date = (
        asof_date - timedelta(days=asof_date.weekday()) - timedelta(days=3)
    )  # 上周五
    cur_end_date = cur_begin_date + timedelta(days=6)

    if cur_end_date < asof_date:
        cur_begin_date += timedelta(days=7)
        cur_end_date += timedelta(days=7)

    pre_begin_date = cur_begin_date - timedelta(days=7)
    pre_end_date = cur_begin_date - timedelta(days=1)

    pre_corresponding_end_date = asof_date - timedelta(days=7)

    return (
        cur_begin_date,
        cur_end_date,
        pre_begin_date,
        pre_end_date,
        pre_corresponding_end_date,
    )


def _wealth_offline_monthly_dates(
    asof_date: date,
) -> tuple[date, date, date, date, date]:
    cur_begin_date = date(asof_date.year, asof_date.month, 1)
    next_begin_date = (
        date(asof_date.year, asof_date.month + 1, 1)
        if asof_date.month != 12
        else date(asof_date.year + 1, 1, 1)
    )
    cur_end_date = next_begin_date - timedelta(days=1)

    pre_begin_date = (
        date(cur_begin_date.year, cur_begin_date.month - 1, 1)
        if cur_begin_date.month != 1
        else date(cur_begin_date.year - 1, 12, 1)
    )
    pre_end_date = cur_begin_date - timedelta(days=1)

    pre_corresponding_end_date = (
        date(pre_end_date.year, pre_end_date.month, asof_date.day)
        if asof_date.day < pre_end_date.day
        else pre_end_date
    )

    return (
        cur_begin_date,
        cur_end_date,
        pre_begin_date,
        pre_end_date,
        pre_corresponding_end_date,
    )


def generate_wealth_sales_performance_report(
    p_begin_date, p_end_date, result_file_path
):
    """生成财富中心销售业绩跟进报表结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/wealth_sales_performance_report_template.xlsx",
    )
    sql_content = get_file_content(
        "sql/ads/wealth_report/wealth_sales_performance_report.sql"
    )

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    title = (
        f"截止{p_end_date.month}月底业绩({p_begin_date.year}.{p_begin_date.month}.{p_begin_date.day}-{p_end_date.year}"
        f".{p_end_date.month}.{p_end_date.day})"
    )
    worksheet["A1"].value = title

    row_num = 4
    for (
        team,
        service_staff,
        seq,
        commission_hkd,
        interest_hkd,
        bond_hkd,
        fund_hkd,
        asset_hkd,
        deposit_hkd,
        valid_num,
        pi_num,
    ) in ads_hook.get_records(
        sql_content.format(
            p_begin_date=p_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
        )
    ):
        worksheet[f"A{row_num}"].value = team
        worksheet[f"B{row_num}"].value = service_staff
        worksheet[f"C{row_num}"].value = _to_float(commission_hkd)
        worksheet[f"D{row_num}"].value = _to_float(interest_hkd)
        worksheet[f"E{row_num}"].value = _to_float(bond_hkd)
        worksheet[f"F{row_num}"].value = _to_float(fund_hkd)
        worksheet[f"G{row_num}"].value = _to_float(asset_hkd)
        worksheet[f"H{row_num}"].value = _to_float(deposit_hkd)
        worksheet[f"I{row_num}"].value = valid_num
        worksheet[f"J{row_num}"].value = pi_num

        row_num += 1

    workbook.save(result_file_path)


def generate_operation_marketing_channel_cooperation_report(
    p_begin_date, p_end_date, result_file_path
):
    """生成运营市场渠道合作数据报表结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/operation_explore/operation_marketing_channel_cooperation_report_template.xlsx",
    )
    sql_content = get_file_content(
        "sql/ads/operation_explore/operation_marketing_channel_cooperation_report.sql"
    )

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    results = ads_hook.get_records(
        sql_content.format(
            p_begin_date=p_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
        )
    )

    highlight_fill = openpyxl.styles.PatternFill(
        fill_type="solid", start_color="FFD700", end_color="FFD700"
    )

    row_num = 2
    for (
        channel_code,
        channel_name,
        top_channel_code,
        level,
        reg_new_num,
        reg_total_num,
        reg_year_new_num,
        open_new_num,
        open_total_num,
        open_year_new_num,
        pay_new_num,
        pay_total_num,
        pay_year_new_num,
        valid_new_num,
        valid_total_num,
        valid_year_new_num,
    ) in results:
        worksheet[f"A{row_num}"].value = (" " * (level - 1) * 4) + channel_code
        worksheet[f"B{row_num}"].value = channel_name
        worksheet[f"C{row_num}"].value = level
        worksheet[f"D{row_num}"].value = reg_new_num
        worksheet[f"E{row_num}"].value = open_new_num
        worksheet[f"F{row_num}"].value = pay_new_num
        worksheet[f"G{row_num}"].value = valid_new_num
        worksheet[f"H{row_num}"].value = reg_year_new_num
        worksheet[f"I{row_num}"].value = open_year_new_num
        worksheet[f"J{row_num}"].value = pay_year_new_num
        worksheet[f"K{row_num}"].value = valid_year_new_num
        worksheet[f"L{row_num}"].value = reg_total_num
        worksheet[f"M{row_num}"].value = open_total_num
        worksheet[f"N{row_num}"].value = pay_total_num
        worksheet[f"O{row_num}"].value = valid_total_num

        if level == 1:
            worksheet[f"A{row_num}"].fill = highlight_fill
            worksheet[f"B{row_num}"].fill = highlight_fill
            worksheet[f"C{row_num}"].fill = highlight_fill
            worksheet[f"D{row_num}"].fill = highlight_fill
            worksheet[f"E{row_num}"].fill = highlight_fill
            worksheet[f"F{row_num}"].fill = highlight_fill
            worksheet[f"G{row_num}"].fill = highlight_fill
            worksheet[f"H{row_num}"].fill = highlight_fill
            worksheet[f"I{row_num}"].fill = highlight_fill
            worksheet[f"J{row_num}"].fill = highlight_fill
            worksheet[f"K{row_num}"].fill = highlight_fill
            worksheet[f"L{row_num}"].fill = highlight_fill
            worksheet[f"M{row_num}"].fill = highlight_fill
            worksheet[f"N{row_num}"].fill = highlight_fill
            worksheet[f"O{row_num}"].fill = highlight_fill

        row_num += 1

    workbook.save(result_file_path)


def generate_operation_metric_report(p_report_date, result_file_path):
    """生成运营业务指标周报结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/operation_explore/operation_metric_report_template.xlsx",
    )
    sql_content = get_file_content(
        "sql/ads/operation_explore/operation_metric_report.sql"
    )

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    col_num = 3
    for period, cur_begin, cur_end, pre_begin, pre_end in _operation_metric_periods(
        p_report_date
    ):
        (
            online_cur_acc_open_num,
            online_cur_acc_paying_num,
            online_cur_acc_valid_num,
            online_cur_acc_deposit_ge10k_num,
            online_cur_open_num,
            online_cur_paying_num,
            online_cur_valid_num,
            online_cur_deposit_ge10k_num,
            online_cur_asset_hkd,
            online_cur_acc_commission_hkd,
            online_cur_acc_platform_fee_hkd,
            online_cur_acc_interest_hkd,
            online_cur_acc_ipo_hkd,
            online_cur_commission_hkd,
            online_cur_platform_fee_hkd,
            online_cur_interest_hkd,
            online_cur_ipo_hkd,
            cmhk_cur_acc_open_num,
            cmhk_cur_acc_paying_num,
            cmhk_cur_acc_valid_num,
            cmhk_cur_acc_deposit_ge10k_num,
            cmhk_cur_asset_hkd,
            cmhk_cur_acc_commission_hkd,
            cmhk_cur_acc_platform_fee_hkd,
            cmhk_cur_acc_interest_hkd,
            cmhk_cur_acc_ipo_hkd,
            ths_cur_acc_open_num,
            ths_cur_acc_paying_num,
            ths_cur_acc_valid_num,
            ths_cur_acc_deposit_ge10k_num,
            ths_cur_open_num,
            ths_cur_paying_num,
            ths_cur_valid_num,
            ths_cur_deposit_ge10k_num,
            ths_cur_asset_hkd,
            ths_cur_acc_commission_hkd,
            ths_cur_acc_platform_fee_hkd,
            ths_cur_acc_interest_hkd,
            ths_cur_acc_ipo_hkd,
            ths_cur_commission_hkd,
            ths_cur_platform_fee_hkd,
            ths_cur_interest_hkd,
            ths_cur_ipo_hkd,
            mainland_cur_acc_open_num,
            mainland_cur_acc_paying_num,
            mainland_cur_acc_valid_num,
            mainland_cur_acc_deposit_ge10k_num,
            mainland_cur_open_num,
            mainland_cur_paying_num,
            mainland_cur_valid_num,
            mainland_cur_deposit_ge10k_num,
            mainland_cur_asset_hkd,
            mainland_cur_acc_commission_hkd,
            mainland_cur_acc_platform_fee_hkd,
            mainland_cur_acc_interest_hkd,
            mainland_cur_acc_ipo_hkd,
            mainland_cur_commission_hkd,
            mainland_cur_platform_fee_hkd,
            mainland_cur_interest_hkd,
            mainland_cur_ipo_hkd,
            oversea_cur_acc_open_num,
            oversea_cur_acc_paying_num,
            oversea_cur_acc_valid_num,
            oversea_cur_acc_deposit_ge10k_num,
            oversea_cur_open_num,
            oversea_cur_paying_num,
            oversea_cur_valid_num,
            oversea_cur_deposit_ge10k_num,
            oversea_cur_asset_hkd,
            oversea_cur_acc_commission_hkd,
            oversea_cur_acc_platform_fee_hkd,
            oversea_cur_acc_interest_hkd,
            oversea_cur_acc_ipo_hkd,
            oversea_cur_commission_hkd,
            oversea_cur_platform_fee_hkd,
            oversea_cur_interest_hkd,
            oversea_cur_ipo_hkd,
            all_cur_acc_open_num,
            all_cur_acc_paying_num,
            all_cur_acc_valid_num,
            all_cur_acc_deposit_ge10k_num,
            all_cur_open_num,
            all_cur_paying_num,
            all_cur_valid_num,
            all_cur_deposit_ge10k_num,
            all_cur_asset_hkd,
            all_cur_acc_commission_hkd,
            all_cur_acc_platform_fee_hkd,
            all_cur_acc_interest_hkd,
            all_cur_acc_ipo_hkd,
            all_cur_commission_hkd,
            all_cur_platform_fee_hkd,
            all_cur_interest_hkd,
            all_cur_ipo_hkd,
            all_pre_acc_open_num,
            all_pre_acc_paying_num,
            all_pre_acc_valid_num,
            all_pre_acc_deposit_ge10k_num,
            all_pre_open_num,
            all_pre_paying_num,
            all_pre_valid_num,
            all_pre_deposit_ge10k_num,
            all_pre_asset_hkd,
            all_pre_acc_commission_hkd,
            all_pre_acc_platform_fee_hkd,
            all_pre_acc_interest_hkd,
            all_pre_acc_ipo_hkd,
            all_pre_commission_hkd,
            all_pre_platform_fee_hkd,
            all_pre_interest_hkd,
            all_pre_ipo_hkd,
            all_acc_open_num_change_rate,
            all_acc_paying_num_change_rate,
            all_acc_valid_num_change_rate,
            all_acc_deposit_ge10k_num_change_rate,
            all_open_num_change_rate,
            all_paying_num_change_rate,
            all_valid_num_change_rate,
            all_deposit_ge10k_num_change_rate,
            all_asset_hkd_change_rate,
            all_acc_commission_hkd_change_rate,
            all_acc_platform_fee_hkd_change_rate,
            all_acc_interest_hkd_change_rate,
            all_acc_ipo_hkd_change_rate,
            all_commission_hkd_change_rate,
            all_platform_fee_hkd_change_rate,
            all_interest_hkd_change_rate,
            all_ipo_hkd_change_rate,
        ) = ads_hook.get_first(
            sql_content.format(
                p_cur_begin_date=cur_begin.strftime(date_fmt),
                p_cur_end_date=cur_end.strftime(date_fmt),
                p_pre_begin_date=pre_begin.strftime(date_fmt),
                p_pre_end_date=pre_end.strftime(date_fmt),
            )
        )
        if period == "M":
            worksheet[
                "A1"
            ].value = f"{cur_begin.strftime(date_fmt)} ~ {cur_end.strftime(date_fmt)}"

            worksheet.cell(column=col_num, row=3, value=online_cur_acc_open_num)
            worksheet.cell(column=col_num, row=4, value=online_cur_acc_paying_num)
            worksheet.cell(column=col_num, row=5, value=online_cur_acc_valid_num)
            worksheet.cell(
                column=col_num, row=6, value=online_cur_acc_deposit_ge10k_num
            )
            worksheet.cell(column=col_num, row=7, value=_to_float(online_cur_asset_hkd))
            worksheet.cell(
                column=col_num, row=8, value=_to_float(online_cur_acc_commission_hkd)
            )
            worksheet.cell(
                column=col_num, row=9, value=_to_float(online_cur_acc_platform_fee_hkd)
            )
            worksheet.cell(
                column=col_num, row=10, value=_to_float(online_cur_acc_interest_hkd)
            )
            worksheet.cell(
                column=col_num, row=11, value=_to_float(online_cur_acc_ipo_hkd)
            )
            col_num += 1

            worksheet.cell(column=col_num, row=3, value=ths_cur_acc_open_num)
            worksheet.cell(column=col_num, row=4, value=ths_cur_acc_paying_num)
            worksheet.cell(column=col_num, row=5, value=ths_cur_acc_valid_num)
            worksheet.cell(column=col_num, row=6, value=ths_cur_acc_deposit_ge10k_num)
            worksheet.cell(column=col_num, row=7, value=_to_float(ths_cur_asset_hkd))
            worksheet.cell(
                column=col_num, row=8, value=_to_float(ths_cur_acc_commission_hkd)
            )
            worksheet.cell(
                column=col_num, row=9, value=_to_float(ths_cur_acc_platform_fee_hkd)
            )
            worksheet.cell(
                column=col_num, row=10, value=_to_float(ths_cur_acc_interest_hkd)
            )
            worksheet.cell(column=col_num, row=11, value=_to_float(ths_cur_acc_ipo_hkd))
            col_num += 1

            worksheet.cell(column=col_num, row=3, value=mainland_cur_acc_open_num)
            worksheet.cell(column=col_num, row=4, value=mainland_cur_acc_paying_num)
            worksheet.cell(column=col_num, row=5, value=mainland_cur_acc_valid_num)
            worksheet.cell(
                column=col_num, row=6, value=mainland_cur_acc_deposit_ge10k_num
            )
            worksheet.cell(
                column=col_num, row=7, value=_to_float(mainland_cur_asset_hkd)
            )
            worksheet.cell(
                column=col_num, row=8, value=_to_float(mainland_cur_acc_commission_hkd)
            )
            worksheet.cell(
                column=col_num,
                row=9,
                value=_to_float(mainland_cur_acc_platform_fee_hkd),
            )
            worksheet.cell(
                column=col_num, row=10, value=_to_float(mainland_cur_acc_interest_hkd)
            )
            worksheet.cell(
                column=col_num, row=11, value=_to_float(mainland_cur_acc_ipo_hkd)
            )
            col_num += 1

            worksheet.cell(column=col_num, row=3, value=oversea_cur_acc_open_num)
            worksheet.cell(column=col_num, row=4, value=oversea_cur_acc_paying_num)
            worksheet.cell(column=col_num, row=5, value=oversea_cur_acc_valid_num)
            worksheet.cell(
                column=col_num, row=6, value=oversea_cur_acc_deposit_ge10k_num
            )
            worksheet.cell(
                column=col_num, row=7, value=_to_float(oversea_cur_asset_hkd)
            )
            worksheet.cell(
                column=col_num, row=8, value=_to_float(oversea_cur_acc_commission_hkd)
            )
            worksheet.cell(
                column=col_num, row=9, value=_to_float(oversea_cur_acc_platform_fee_hkd)
            )
            worksheet.cell(
                column=col_num, row=10, value=_to_float(oversea_cur_acc_interest_hkd)
            )
            worksheet.cell(
                column=col_num, row=11, value=_to_float(oversea_cur_acc_ipo_hkd)
            )
            col_num += 1

            worksheet.cell(column=col_num, row=3, value=cmhk_cur_acc_open_num)
            worksheet.cell(column=col_num, row=4, value=cmhk_cur_acc_paying_num)
            worksheet.cell(column=col_num, row=5, value=cmhk_cur_acc_valid_num)
            worksheet.cell(column=col_num, row=6, value=cmhk_cur_acc_deposit_ge10k_num)
            worksheet.cell(column=col_num, row=7, value=_to_float(cmhk_cur_asset_hkd))
            worksheet.cell(
                column=col_num, row=8, value=_to_float(cmhk_cur_acc_commission_hkd)
            )
            worksheet.cell(
                column=col_num, row=9, value=_to_float(cmhk_cur_acc_platform_fee_hkd)
            )
            worksheet.cell(
                column=col_num, row=10, value=_to_float(cmhk_cur_acc_interest_hkd)
            )
            worksheet.cell(
                column=col_num, row=11, value=_to_float(cmhk_cur_acc_ipo_hkd)
            )
            col_num += 1

            # 当前月累计
        if period == "W" or col_num == 8:
            worksheet.cell(
                column=col_num,
                row=1,
                value=f"{cur_begin.month}.{cur_begin.day} - {cur_end.month}.{cur_end.day}",
            )

            worksheet.cell(column=col_num, row=3, value=ths_cur_open_num)
            worksheet.cell(column=col_num, row=4, value=ths_cur_paying_num)
            worksheet.cell(column=col_num, row=5, value=ths_cur_valid_num)
            worksheet.cell(column=col_num, row=6, value=ths_cur_deposit_ge10k_num)
            worksheet.cell(column=col_num, row=7, value=_to_float(ths_cur_asset_hkd))
            worksheet.cell(
                column=col_num, row=8, value=_to_float(ths_cur_commission_hkd)
            )
            worksheet.cell(
                column=col_num, row=9, value=_to_float(ths_cur_platform_fee_hkd)
            )
            worksheet.cell(
                column=col_num, row=10, value=_to_float(ths_cur_interest_hkd)
            )
            worksheet.cell(column=col_num, row=11, value=_to_float(ths_cur_ipo_hkd))
            col_num += 1

            worksheet.cell(column=col_num, row=3, value=mainland_cur_open_num)
            worksheet.cell(column=col_num, row=4, value=mainland_cur_paying_num)
            worksheet.cell(column=col_num, row=5, value=mainland_cur_valid_num)
            worksheet.cell(column=col_num, row=6, value=mainland_cur_deposit_ge10k_num)
            worksheet.cell(
                column=col_num, row=7, value=_to_float(mainland_cur_asset_hkd)
            )
            worksheet.cell(
                column=col_num, row=8, value=_to_float(mainland_cur_commission_hkd)
            )
            worksheet.cell(
                column=col_num, row=9, value=_to_float(mainland_cur_platform_fee_hkd)
            )
            worksheet.cell(
                column=col_num, row=10, value=_to_float(mainland_cur_interest_hkd)
            )
            worksheet.cell(
                column=col_num, row=11, value=_to_float(mainland_cur_ipo_hkd)
            )
            col_num += 1

            worksheet.cell(column=col_num, row=3, value=oversea_cur_open_num)
            worksheet.cell(column=col_num, row=4, value=oversea_cur_paying_num)
            worksheet.cell(column=col_num, row=5, value=oversea_cur_valid_num)
            worksheet.cell(column=col_num, row=6, value=oversea_cur_deposit_ge10k_num)
            worksheet.cell(
                column=col_num, row=7, value=_to_float(oversea_cur_asset_hkd)
            )
            worksheet.cell(
                column=col_num, row=8, value=_to_float(oversea_cur_commission_hkd)
            )
            worksheet.cell(
                column=col_num, row=9, value=_to_float(oversea_cur_platform_fee_hkd)
            )
            worksheet.cell(
                column=col_num, row=10, value=_to_float(oversea_cur_interest_hkd)
            )
            worksheet.cell(column=col_num, row=11, value=_to_float(oversea_cur_ipo_hkd))
            col_num += 1

            worksheet.cell(column=col_num, row=3, value=all_cur_open_num)
            worksheet.cell(column=col_num, row=4, value=all_cur_paying_num)
            worksheet.cell(column=col_num, row=5, value=all_cur_valid_num)
            worksheet.cell(column=col_num, row=6, value=all_cur_deposit_ge10k_num)
            worksheet.cell(column=col_num, row=7, value=_to_float(all_cur_asset_hkd))
            worksheet.cell(
                column=col_num, row=8, value=_to_float(all_cur_commission_hkd)
            )
            worksheet.cell(
                column=col_num, row=9, value=_to_float(all_cur_platform_fee_hkd)
            )
            worksheet.cell(
                column=col_num, row=10, value=_to_float(all_cur_interest_hkd)
            )
            worksheet.cell(column=col_num, row=11, value=_to_float(all_cur_ipo_hkd))
            col_num += 1

            worksheet.cell(
                column=col_num, row=3, value=_to_float(all_open_num_change_rate)
            )
            worksheet.cell(
                column=col_num, row=4, value=_to_float(all_paying_num_change_rate)
            )
            worksheet.cell(
                column=col_num, row=5, value=_to_float(all_valid_num_change_rate)
            )
            worksheet.cell(
                column=col_num,
                row=6,
                value=_to_float(all_deposit_ge10k_num_change_rate),
            )
            worksheet.cell(
                column=col_num, row=7, value=_to_float(all_asset_hkd_change_rate)
            )
            worksheet.cell(
                column=col_num, row=8, value=_to_float(all_commission_hkd_change_rate)
            )
            worksheet.cell(
                column=col_num, row=9, value=_to_float(all_platform_fee_hkd_change_rate)
            )
            worksheet.cell(
                column=col_num, row=10, value=_to_float(all_interest_hkd_change_rate)
            )
            worksheet.cell(
                column=col_num, row=11, value=_to_float(all_ipo_hkd_change_rate)
            )
            col_num += 1

    # 删除不需要的模板列
    worksheet.delete_cols(col_num, 30)

    workbook.save(result_file_path)


def _operation_metric_periods(report_date):
    # monthly
    cur_month_begin = date(year=report_date.year, month=report_date.month, day=1)
    next_month_someday = cur_month_begin + timedelta(days=40)
    cur_month_end = date(
        year=next_month_someday.year, month=next_month_someday.month, day=1
    ) - timedelta(days=1)

    pre_month_begin = date(
        year=cur_month_begin.year - 1
        if cur_month_begin.month == 1
        else cur_month_begin.year,
        month=12 if cur_month_begin.month == 1 else cur_month_begin.month - 1,
        day=1,
    )
    pre_month_end = report_date - timedelta(days=31)
    if pre_month_end < pre_month_begin:
        pre_month_end = pre_month_begin

    yield "M", cur_month_begin, cur_month_end, pre_month_begin, pre_month_end

    # weekly
    cur_week_begin = (
        cur_month_begin - timedelta(days=cur_month_begin.weekday()) - timedelta(days=3)
    )  # 周五
    cur_week_end = cur_week_begin + timedelta(days=6)  # 周四
    while cur_week_begin <= report_date:
        if cur_week_end < cur_month_begin:
            pass
        else:
            yield (
                "W",
                cur_week_begin,
                cur_week_end,
                cur_week_begin - timedelta(days=7),
                cur_week_end - timedelta(days=7),
            )

        cur_week_begin += timedelta(days=7)
        cur_week_end += timedelta(days=7)


def generate_operation_indep_dev_online_report(p_report_date, result_file_path):
    """生成运营自研App线上数据日报结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/operation_explore/operation_indep_dev_online_report_template.xlsx",
    )
    sql_content = get_file_content(
        "sql/ads/operation_explore/operation_indep_dev_online_report.sql"
    )

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    results = ads_hook.get_records(
        sql_content.format(p_report_date=p_report_date.strftime(date_fmt))
    )

    row_num = 2
    for (
        ae_code,
        reg_today_num,
        reg_mtd_num,
        reg_ytd_num,
        reg_acc_num,
        open_today_num,
        open_mtd_num,
        open_ytd_num,
        open_acc_num,
        pay_today_num,
        pay_mtd_num,
        pay_ytd_num,
        pay_acc_num,
        valid_today_num,
        valid_mtd_num,
        valid_ytd_num,
        valid_acc_num,
        revenue_today,
        revenue_mtd,
        revenue_ytd,
        revenue_acc,
    ) in results:
        worksheet[f"A{row_num}"].value = ae_code
        worksheet[f"B{row_num}"].value = reg_today_num
        worksheet[f"C{row_num}"].value = open_today_num
        worksheet[f"D{row_num}"].value = pay_today_num
        worksheet[f"E{row_num}"].value = valid_today_num
        worksheet[f"F{row_num}"].value = _to_float(revenue_today)
        worksheet[f"G{row_num}"].value = reg_mtd_num
        worksheet[f"H{row_num}"].value = open_mtd_num
        worksheet[f"I{row_num}"].value = pay_mtd_num
        worksheet[f"J{row_num}"].value = valid_mtd_num
        worksheet[f"K{row_num}"].value = _to_float(revenue_mtd)
        worksheet[f"L{row_num}"].value = reg_ytd_num
        worksheet[f"M{row_num}"].value = open_ytd_num
        worksheet[f"N{row_num}"].value = pay_ytd_num
        worksheet[f"O{row_num}"].value = valid_ytd_num
        worksheet[f"P{row_num}"].value = _to_float(revenue_ytd)
        worksheet[f"Q{row_num}"].value = reg_acc_num
        worksheet[f"R{row_num}"].value = open_acc_num
        worksheet[f"S{row_num}"].value = pay_acc_num
        worksheet[f"T{row_num}"].value = valid_acc_num
        worksheet[f"U{row_num}"].value = _to_float(revenue_acc)

        row_num += 1

    workbook.save(result_file_path)


def generate_operation_oversea_account_list(result_file_path):
    """生成运营香港及海外已开户客户列表Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/operation_explore/operation_oversea_account_list_template.xlsx",
    )
    sql_content = """select
    open_date,uin,hlid,email,invite_channel_code,c.channel_name
from ads.common_integrated_base_info b
left join dim.dim_channel c
    on b.ae_code=c.ae_code and b.invite_channel_code=c.channel_code
where
    belonging_region='OVERSEA'
    and account_status='A'
    and client_id in (
        select client_id
        from dim.dim_client
        where
            source_system_code<>'IASIA'
    )
    and uin>0
order by uin"""

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    results = ads_hook.get_records(sql_content)

    row_num = 2
    for open_date, uin, hlid, email, invite_channel_code, channel_name in results:
        worksheet[f"A{row_num}"].value = _to_date(open_date)
        worksheet[f"B{row_num}"].value = uin
        worksheet[f"C{row_num}"].value = hlid
        worksheet[f"D{row_num}"].value = email
        worksheet[f"E{row_num}"].value = invite_channel_code
        worksheet[f"F{row_num}"].value = channel_name

        row_num += 1

    workbook.save(result_file_path)


def generate_operation_mgm_group_inviter_report(p_report_date, result_file_path):
    """生成运营超级团长邀约用户统计Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/operation_explore/operation_mgm_group_inviter_report_template.xlsx",
    )
    sql_content = get_file_content(
        "sql/ads/operation_explore/operation_mgm_group_inviter_report.sql"
    )

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)

    for p_activity_type in ("CN", "HK"):
        worksheet_name = "国内超级团长" if p_activity_type == "CN" else "香港超级团长"
        worksheet = workbook[worksheet_name]

        results = ads_hook.get_records(
            sql_content.format(
                p_report_date=p_report_date.strftime(date_fmt),
                p_activity_type=p_activity_type,
            )
        )

        if results:
            row_num = 2
            for (
                account_no,
                hlid,
                name,
                reg_today_num,
                reg_mtd_num,
                reg_ytd_num,
                reg_total_num,
                open_today_num,
                open_mtd_num,
                open_ytd_num,
                open_total_num,
                first_deposit_today_num,
                first_deposit_mtd_num,
                first_deposit_ytd_num,
                first_deposit_total_num,
                valid_today_num,
                valid_mtd_num,
                valid_ytd_num,
                valid_total_num,
            ) in results:
                worksheet[f"A{row_num}"].value = account_no
                worksheet[f"B{row_num}"].value = hlid
                worksheet[f"C{row_num}"].value = name
                worksheet[f"D{row_num}"].value = reg_today_num
                worksheet[f"E{row_num}"].value = open_today_num
                worksheet[f"F{row_num}"].value = first_deposit_today_num
                worksheet[f"G{row_num}"].value = valid_today_num
                worksheet[f"H{row_num}"].value = reg_mtd_num
                worksheet[f"I{row_num}"].value = open_mtd_num
                worksheet[f"J{row_num}"].value = first_deposit_mtd_num
                worksheet[f"K{row_num}"].value = valid_mtd_num
                worksheet[f"L{row_num}"].value = reg_ytd_num
                worksheet[f"M{row_num}"].value = open_ytd_num
                worksheet[f"N{row_num}"].value = first_deposit_ytd_num
                worksheet[f"O{row_num}"].value = valid_ytd_num
                worksheet[f"P{row_num}"].value = reg_total_num
                worksheet[f"Q{row_num}"].value = open_total_num
                worksheet[f"R{row_num}"].value = first_deposit_total_num
                worksheet[f"S{row_num}"].value = valid_total_num

                row_num += 1
        else:
            worksheet["A2"].value = "无"

    workbook.save(result_file_path)


def generate_proprietary_business_trade_report(
    p_report_date, p_us_date, result_file_path
):
    """生成自营账户交易明细结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/proprietary_business/proprietary_business_trade_report_template.xlsx",
    )
    sql_content = get_file_content(
        "sql/ads/proprietary_business/proprietary_business_trade_report.sql"
    )

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    results = ads_hook.get_records(
        sql_content.format(
            p_report_date=p_report_date.strftime(date_fmt),
            p_us_date=p_us_date.strftime(date_fmt),
        )
    )

    update_us_date = False
    if not results:
        worksheet["A2"] = "无"
    else:
        row_num = 2
        for (
            trade_date,
            settle_date,
            ticker,
            name,
            isin_code,
            trade_type_desc,
            quantity,
            currency_code,
            price,
            gross_amount,
            settle_amount,
            commission,
            local_levy,
            stamp_duty,
            clearing_fee,
            trade_fee,
            frc_levy,
            is_us,
        ) in results:
            worksheet[f"A{row_num}"].value = _to_date(trade_date)
            worksheet[f"B{row_num}"].value = _to_date(settle_date)
            worksheet[f"C{row_num}"].value = ticker
            worksheet[f"D{row_num}"].value = name
            worksheet[f"E{row_num}"].value = isin_code
            worksheet[f"F{row_num}"].value = trade_type_desc
            worksheet[f"G{row_num}"].value = _to_float(quantity)
            worksheet[f"H{row_num}"].value = currency_code
            worksheet[f"I{row_num}"].value = _to_float(price)
            worksheet[f"J{row_num}"].value = _to_float(gross_amount)
            worksheet[f"K{row_num}"].value = _to_float(settle_amount)
            worksheet[f"L{row_num}"].value = _to_float(commission)
            worksheet[f"M{row_num}"].value = _to_float(local_levy)
            worksheet[f"N{row_num}"].value = _to_float(stamp_duty)
            worksheet[f"O{row_num}"].value = _to_float(clearing_fee)
            worksheet[f"P{row_num}"].value = _to_float(trade_fee)
            worksheet[f"Q{row_num}"].value = _to_float(frc_levy)

            if is_us:
                update_us_date = True

            row_num += 1

    workbook.save(result_file_path)

    return update_us_date


def generate_proprietary_business_stock_holding_value_report(
    p_report_date, result_file_path
):
    """生成自营账户股票持仓市值结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/proprietary_business/proprietary_business_stock_holding_value_report_template.xlsx",
    )
    sql_content = get_file_content(
        "sql/ads/proprietary_business/proprietary_business_stock_holding_value_report.sql"
    )

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    results = ads_hook.get_records(
        sql_content.format(p_report_date=p_report_date.strftime(date_fmt))
    )

    if not results:
        worksheet["A2"] = "无"
    else:
        row_num = 2
        for asof_date, market_value_hkd in results:
            worksheet[f"A{row_num}"].value = _to_date(asof_date)
            worksheet[f"B{row_num}"].value = _to_float(market_value_hkd)

            row_num += 1

    workbook.save(result_file_path)


def generate_compliance_staff_trade_report(p_report_date, p_us_date, result_file_path):
    """生成合规员工交易结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/compliance/compliance_staff_trade_report_template.xlsx",
    )
    sql_content = get_file_content(
        "sql/ads/compliance/compliance_staff_trade_report.sql"
    )

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["工作表1"]

    results = ads_hook.get_records(
        sql_content.format(
            p_report_date=p_report_date.strftime(date_fmt),
            p_us_date=p_us_date.strftime(date_fmt),
        )
    )

    update_us_date = False
    if not results:
        worksheet["B3"] = "无"
    else:
        left_alignment = openpyxl.styles.Alignment(horizontal="left")
        wrap_text = openpyxl.styles.Alignment(wrapText=True)

        row_num = 3
        for (
            name_chinese,
            name_english,
            department,
            account_no,
            trade_date,
            security_type,
            trade_type,
            security_name,
            currency_code,
            price,
            is_us,
            apply_dates,
            init_approve_dates,
            management_approve_dates,
            legal_approve_dates,
            apply_contents,
        ) in results:
            worksheet[f"B{row_num}"].value = name_chinese
            worksheet[f"C{row_num}"].value = name_english
            worksheet[f"D{row_num}"].value = department
            worksheet[f"E{row_num}"].value = account_no
            worksheet[f"F{row_num}"].value = _to_date(trade_date)
            worksheet[f"F{row_num}"].alignment = left_alignment
            worksheet[f"G{row_num}"].value = security_type
            worksheet[f"H{row_num}"].value = trade_type
            worksheet[f"I{row_num}"].value = security_name
            worksheet[f"J{row_num}"].value = currency_code
            worksheet[f"K{row_num}"].value = _to_float(price)
            worksheet[f"K{row_num}"].alignment = left_alignment
            worksheet[f"L{row_num}"].value = apply_dates
            worksheet[f"L{row_num}"].alignment = wrap_text
            worksheet[f"M{row_num}"].value = init_approve_dates
            worksheet[f"M{row_num}"].alignment = wrap_text
            worksheet[f"N{row_num}"].value = management_approve_dates
            worksheet[f"N{row_num}"].alignment = wrap_text
            worksheet[f"O{row_num}"].value = legal_approve_dates
            worksheet[f"O{row_num}"].alignment = wrap_text
            worksheet[f"P{row_num}"].value = apply_contents
            worksheet[f"P{row_num}"].alignment = wrap_text

            if is_us:
                update_us_date = True

            row_num += 1

    workbook.save(result_file_path)

    return update_us_date


def generate_compliance_weekly_wealth_trade_report(
    p_begin_date: date, p_end_date: date, result_file_path: str
):
    """生成法务合规部-每周数据报表财富交易明细Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/compliance/compliance_weekly_wealth_trade_report_template.xlsx",
    )

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)
    worksheet_trade_detail = workbook["交易明细"]

    sql_trade = """with
    toDate32('{p_begin_date}') as p_begin_date,
    toDate32('{p_end_date}') as p_end_date
select
    t.trade_date as trade_date,
    t.trade_type_desc as trade_type,
    case
        when a.name_chinese<>'' then a.name_chinese
        else a.name_english
    end as account_name,
    t.account_no as account_no,
    a.client_type_desc as client_type,
    t.currency_code as currency_code,
    t.gross_amount as gross_amount,
    ifNull(b.level2_name,'') as business_line,
    case
        when s.name_chinese<>'' then s.name_chinese
        else s.name_english
    end as security_name,
    case
        when st.end_date is null or st.end_date>=t.trade_date then st.staff_name
        else ''
    end as licensed_staff,
    case
        when t.biz_line_key like 'WEALTH|FUND%MMF%' then 1
        else 0
    end as is_mmf,
    case
        when a.aml_risk_level='高' then 1
        else 0
    end as is_high_aml_risk,
    case
        when t.biz_line_key like 'WEALTH%' then 1
        else 0
    end as is_wealth
from (
    select
        ref_no,trade_date,account_no,security_key,trade_type_desc,currency_code,biz_line_key,gross_amount,ae_code
    from dwd.dwd_trade
    where
        trade_date between p_begin_date and p_end_date
    union all
    select
        ref_no,trade_date,account_no,security_key,trade_type_desc,currency_code,biz_line_key,gross_amount,ae_code
    from dwd.dwd_extra_trade
    where
        trade_date between p_begin_date and p_end_date
) t
inner join dim.dim_account a
    on t.account_no=a.account_no
inner join dim.dim_security s
    on t.security_key=s.security_key
left join dim.dim_business_line b
    on t.biz_line_key=b.biz_line_key
left asof join (
    select
        m.ae_code as ae_code,
        m.begin_date as begin_date,
        m.end_date as end_date,
        s.staff_name as staff_name
    from dim.ref_ae_member m
    inner join dim.dim_staff s
        on m.staff_id=s.staff_id
    where
        role_id=2 -- 持牌代表
) st
    on t.ae_code=st.ae_code and t.trade_date>=st.begin_date
order by t.trade_date,t.account_no,t.ref_no"""

    row_no_trade_detail = 2
    for (
        trade_date,
        trade_type,
        account_name,
        account_no,
        client_type,
        currency_code,
        gross_amount,
        business_line,
        security_name,
        licensed_staff,
        is_mmf,
        is_high_aml_risk,
        is_wealth,
    ) in ads_hook.get_records(
        sql_trade.format(
            p_begin_date=p_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
        )
    ):
        if is_mmf == 0 and is_wealth == 1:
            worksheet_trade_detail[f"A{row_no_trade_detail}"].value = trade_date
            worksheet_trade_detail[f"B{row_no_trade_detail}"].value = trade_type
            worksheet_trade_detail[f"C{row_no_trade_detail}"].value = account_name
            worksheet_trade_detail[f"D{row_no_trade_detail}"].value = account_no
            worksheet_trade_detail[f"E{row_no_trade_detail}"].value = client_type
            worksheet_trade_detail[f"F{row_no_trade_detail}"].value = currency_code
            worksheet_trade_detail[f"G{row_no_trade_detail}"].value = _to_float(
                gross_amount
            )
            worksheet_trade_detail[f"H{row_no_trade_detail}"].value = business_line
            worksheet_trade_detail[f"I{row_no_trade_detail}"].value = security_name
            worksheet_trade_detail[f"J{row_no_trade_detail}"].value = licensed_staff
            row_no_trade_detail += 1

    workbook.save(result_file_path)


def generate_compliance_monthly_high_aml_risk_trade_movement_report(
    p_begin_date: date, p_end_date: date, result_file_path: str
):
    """生成法务合规部-每月数据报表高风险客户交易和出入金明细Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/compliance/"
        "compliance_monthly_high_aml_risk_trade_movement_report_template.xlsx",
    )

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)
    worksheet_high_aml_risk_trade = workbook["高风险客户交易"]
    worksheet_high_aml_risk_cash_movement = workbook["高风险客户出入金"]

    sql_trade = """with
    toDate32('{p_begin_date}') as p_begin_date,
    toDate32('{p_end_date}') as p_end_date
select
    t.trade_date as trade_date,
    t.trade_type_desc as trade_type,
    case
        when a.name_chinese<>'' then a.name_chinese
        else a.name_english
    end as account_name,
    t.account_no as account_no,
    a.client_type_desc as client_type,
    t.currency_code as currency_code,
    t.gross_amount as gross_amount,
    ifNull(b.level2_name,'') as business_line,
    case
        when s.name_chinese<>'' then s.name_chinese
        else s.name_english
    end as security_name,
    case
        when st.end_date is null or st.end_date>=t.trade_date then st.staff_name
        else ''
    end as licensed_staff,
    case
        when t.biz_line_key like 'WEALTH|FUND%MMF%' then 1
        else 0
    end as is_mmf,
    case
        when a.aml_risk_level='高' then 1
        else 0
    end as is_high_aml_risk,
    case
        when t.biz_line_key like 'WEALTH%' then 1
        else 0
    end as is_wealth
from (
    select
        ref_no,trade_date,account_no,security_key,trade_type_desc,currency_code,biz_line_key,gross_amount,ae_code
    from dwd.dwd_trade
    where
        trade_date between p_begin_date and p_end_date
    union all
    select
        ref_no,trade_date,account_no,security_key,trade_type_desc,currency_code,biz_line_key,gross_amount,ae_code
    from dwd.dwd_extra_trade
    where
        trade_date between p_begin_date and p_end_date
) t
inner join dim.dim_account a
    on t.account_no=a.account_no
inner join dim.dim_security s
    on t.security_key=s.security_key
left join dim.dim_business_line b
    on t.biz_line_key=b.biz_line_key
left asof join (
    select
        m.ae_code as ae_code,
        m.begin_date as begin_date,
        m.end_date as end_date,
        s.staff_name as staff_name
    from dim.ref_ae_member m
    inner join dim.dim_staff s
        on m.staff_id=s.staff_id
    where
        role_id=2 -- 持牌代表
) st
    on t.ae_code=st.ae_code and t.trade_date>=st.begin_date
order by t.trade_date,t.account_no,t.ref_no"""

    sql_cash_movement = """with
    toDate32('{p_begin_date}') as p_begin_date,
    toDate32('{p_end_date}') as p_end_date
select
    m.trade_date as trade_date,
    m.movement_type_desc as movement_type,
    case
        when a.name_chinese<>'' then a.name_chinese
        else a.name_english
    end as account_name,
    m.account_no as account_no,
    m.to_bank_account_name as to_bank_account_name,
    m.to_bank_account_no as to_bank_account_no,
    m.from_bank_account_name as from_bank_account_name,
    m.from_bank_account_no as from_bank_account_no,
    m.from_to_relation as from_to_relation,
    m.currency_code as currency_code,
    m.amount as amount,
    case
        when m.audit_ts is not null then '是'
        else '否'
    end as is_approved,
    m.audit_operator_name as audit_operator_name
from dwd.dwd_cash_movement m
inner join dim.dim_account a
    on m.account_no=a.account_no
where
    m.trade_date between p_begin_date and p_end_date
    and m.is_by_client=1
    and a.aml_risk_level='高'
order by m.trade_date,m.account_no,m.ref_no"""

    row_no_high_aml_risk_trade = 2
    for (
        trade_date,
        trade_type,
        account_name,
        account_no,
        client_type,
        currency_code,
        gross_amount,
        business_line,
        security_name,
        licensed_staff,
        is_mmf,
        is_high_aml_risk,
        is_wealth,
    ) in ads_hook.get_records(
        sql_trade.format(
            p_begin_date=p_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
        )
    ):
        if is_high_aml_risk:
            worksheet_high_aml_risk_trade[
                f"A{row_no_high_aml_risk_trade}"
            ].value = trade_date
            worksheet_high_aml_risk_trade[
                f"B{row_no_high_aml_risk_trade}"
            ].value = trade_type
            worksheet_high_aml_risk_trade[
                f"C{row_no_high_aml_risk_trade}"
            ].value = account_name
            worksheet_high_aml_risk_trade[
                f"D{row_no_high_aml_risk_trade}"
            ].value = account_no
            worksheet_high_aml_risk_trade[
                f"E{row_no_high_aml_risk_trade}"
            ].value = client_type
            worksheet_high_aml_risk_trade[
                f"F{row_no_high_aml_risk_trade}"
            ].value = currency_code
            worksheet_high_aml_risk_trade[
                f"G{row_no_high_aml_risk_trade}"
            ].value = _to_float(gross_amount)
            worksheet_high_aml_risk_trade[
                f"H{row_no_high_aml_risk_trade}"
            ].value = business_line
            worksheet_high_aml_risk_trade[
                f"I{row_no_high_aml_risk_trade}"
            ].value = security_name
            worksheet_high_aml_risk_trade[
                f"J{row_no_high_aml_risk_trade}"
            ].value = licensed_staff
            row_no_high_aml_risk_trade += 1

    row_no_high_aml_risk_cash_movement = 2
    for (
        trade_date,
        movement_type,
        account_name,
        account_no,
        to_bank_account_name,
        to_bank_account_no,
        from_bank_account_name,
        from_bank_account_no,
        from_to_relation,
        currency_code,
        amount,
        is_approved,
        audit_operator_name,
    ) in ads_hook.get_records(
        sql_cash_movement.format(
            p_begin_date=p_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
        )
    ):
        worksheet_high_aml_risk_cash_movement[
            f"A{row_no_high_aml_risk_cash_movement}"
        ].value = trade_date
        worksheet_high_aml_risk_cash_movement[
            f"B{row_no_high_aml_risk_cash_movement}"
        ].value = movement_type
        worksheet_high_aml_risk_cash_movement[
            f"C{row_no_high_aml_risk_cash_movement}"
        ].value = account_name
        worksheet_high_aml_risk_cash_movement[
            f"D{row_no_high_aml_risk_cash_movement}"
        ].value = account_no
        worksheet_high_aml_risk_cash_movement[
            f"E{row_no_high_aml_risk_cash_movement}"
        ].value = to_bank_account_name
        worksheet_high_aml_risk_cash_movement[
            f"F{row_no_high_aml_risk_cash_movement}"
        ].value = to_bank_account_no
        worksheet_high_aml_risk_cash_movement[
            f"G{row_no_high_aml_risk_cash_movement}"
        ].value = from_bank_account_name
        worksheet_high_aml_risk_cash_movement[
            f"H{row_no_high_aml_risk_cash_movement}"
        ].value = from_bank_account_no
        worksheet_high_aml_risk_cash_movement[
            f"I{row_no_high_aml_risk_cash_movement}"
        ].value = from_to_relation
        worksheet_high_aml_risk_cash_movement[
            f"J{row_no_high_aml_risk_cash_movement}"
        ].value = currency_code
        worksheet_high_aml_risk_cash_movement[
            f"K{row_no_high_aml_risk_cash_movement}"
        ].value = _to_float(amount)
        worksheet_high_aml_risk_cash_movement[
            f"L{row_no_high_aml_risk_cash_movement}"
        ].value = is_approved
        worksheet_high_aml_risk_cash_movement[
            f"M{row_no_high_aml_risk_cash_movement}"
        ].value = audit_operator_name
        row_no_high_aml_risk_cash_movement += 1

    workbook.save(result_file_path)


def _mark_value(cell, cur, pre=0, flag=True):
    """
    :param cell:当前需要赋值的单元格
    :param cur: 当前需要赋值的内容
    :parma pre: 部分值需要环比，默认是0
    :param flag: 表示是否需要格式处理
    :return:
    """
    green = openpyxl.styles.Font(name="微软雅黑", color="00B050", size=11)
    red = openpyxl.styles.Font(name="微软雅黑", color="FF0000", size=11)
    normal = openpyxl.styles.Font(name="微软雅黑", color="000000", size=11)
    if not f"{cur}".isdigit():
        cur = _to_float(cur) if isinstance(cur, str) else cur
        pre = _to_float(pre) if isinstance(pre, str) else pre
    if flag and float(cur) - float(pre) < 0:
        cell.value = f"{cur} ↓"
        cell.font = green
    elif flag and float(cur) - float(pre) > 0:
        cell.value = f"{cur} ↑"
        cell.font = red
    else:
        cell.value = cur
        cell.font = normal


def generate_hnw_dashboard_report(p_report_date, result_file_path):
    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/operation_explore/operation_hnw_dashboard_template.xlsx",
    )
    sql_content = get_file_content(
        "sql/ads/operation_explore/operation_hnw_dashboard_report.sql"
    )

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")
    workbook = openpyxl.load_workbook(excel_template)
    worksheet_net = workbook["净增长高客数据"]
    worksheet_grow = workbook["新增高客数量"]
    worksheet_loss = workbook["流失高客数量"]

    week_range = [
        p_report_date,
        p_report_date - timedelta(days=7),
        p_report_date - timedelta(days=14),
    ]
    row = 6
    for item in week_range:
        cur_date = item.strftime("%Y-%m-%d")
        (
            cur_year_net_new_grow_hnw_counts,
            pre_week_net_new_grow_hnw_counts,
            cur_year_net_new_grow_normal_counts,
            cur_year_net_new_grow_gold_counts,
            cur_year_net_new_grow_platinum_counts,
            cur_year_net_new_grow_diamond_counts,
            cur_year_net_new_grow_black_counts,
            cur_week_net_new_grow_normal_counts,
            cur_week_net_new_grow_gold_counts,
            cur_week_net_new_grow_platinum_counts,
            cur_week_net_new_grow_diamond_counts,
            cur_week_net_new_grow_black_counts,
            cur_year_net_new_grow_aum_hnw_hkd,
            pre_week_net_new_grow_asset_aum_hnw_hkd,
            cur_year_net_new_grow_aum_normal_hkd,
            cur_year_net_new_grow_aum_gold_hkd,
            cur_year_net_new_grow_aum_platinum_hkd,
            cur_year_net_new_grow_aum_diamond_hkd,
            cur_year_net_new_grow_aum_black_hkd,
            cur_week_net_new_grow_aum_normal_hkd,
            cur_week_net_new_grow_aum_gold_hkd,
            cur_week_net_new_grow_aum_platinum_hkd,
            cur_week_net_new_grow_aum_diamond_hkd,
            cur_week_net_new_grow_aum_black_hkd,
            cur_week_cur_year_net_new_grow_avg_asset_hnw_hkd,
            pre_week_cur_year_net_new_grow_avg_asset_hnw_hkd,
            cur_week_cur_year_net_new_grow_avg_asset_normal_hkd,
            pre_week_cur_year_net_new_grow_avg_asset_normal_hkd,
            cur_week_cur_year_net_new_grow_avg_asset_gold_hkd,
            pre_week_cur_year_net_new_grow_avg_asset_gold_hkd,
            cur_week_cur_year_net_new_grow_avg_asset_platinum_hkd,
            pre_week_cur_year_net_new_grow_avg_asset_platinum_hkd,
            cur_week_cur_year_net_new_grow_avg_asset_diamond_hkd,
            pre_week_cur_year_net_new_grow_avg_asset_diamond_hkd,
            cur_week_cur_year_net_new_grow_avg_asset_black_hkd,
            pre_week_cur_year_net_new_grow_avg_asset_black_hkd,
            cur_year_net_new_grow_aum_hnw_us,
            pre_week_net_new_grow_asset_aum_hnw_us,
            cur_year_net_new_grow_aum_normal_us,
            cur_year_net_new_grow_aum_gold_us,
            cur_year_net_new_grow_aum_platinum_us,
            cur_year_net_new_grow_aum_diamond_us,
            cur_year_net_new_grow_aum_black_us,
            cur_week_net_new_grow_aum_normal_us,
            cur_week_net_new_grow_aum_gold_us,
            cur_week_net_new_grow_aum_platinum_us,
            cur_week_net_new_grow_aum_diamond_us,
            cur_week_net_new_grow_aum_black_us,
            cur_week_cur_year_net_new_grow_avg_asset_hnw_us,
            pre_week_cur_year_net_new_grow_avg_asset_hnw_us,
            cur_week_cur_year_net_new_grow_avg_asset_normal_us,
            pre_week_cur_year_net_new_grow_avg_asset_normal_us,
            cur_week_cur_year_net_new_grow_avg_asset_gold_us,
            pre_week_cur_year_net_new_grow_avg_asset_gold_us,
            cur_week_cur_year_net_new_grow_avg_asset_platinum_us,
            pre_week_cur_year_net_new_grow_avg_asset_platinum_us,
            cur_week_cur_year_net_new_grow_avg_asset_diamond_us,
            pre_week_cur_year_net_new_grow_avg_asset_diamond_us,
            cur_week_cur_year_net_new_grow_avg_asset_black_us,
            pre_week_cur_year_net_new_grow_avg_asset_black_us,
            # 增长值
            cur_year_new_grow_hnw_counts,
            pre_week_new_grow_hnw_counts,
            cur_year_new_grow_normal_counts,
            cur_year_new_grow_gold_counts,
            cur_year_new_grow_platinum_counts,
            cur_year_new_grow_diamond_counts,
            cur_year_new_grow_black_counts,
            cur_week_new_grow_normal_counts,
            cur_week_new_grow_gold_counts,
            cur_week_new_grow_platinum_counts,
            cur_week_new_grow_diamond_counts,
            cur_week_new_grow_black_counts,
            cur_year_new_grow_aum_hnw_hkd,
            pre_week_new_grow_asset_aum_hnw_hkd,
            cur_year_new_grow_aum_normal_hkd,
            cur_year_new_grow_aum_gold_hkd,
            cur_year_new_grow_aum_platinum_hkd,
            cur_year_new_grow_aum_diamond_hkd,
            cur_year_new_grow_aum_black_hkd,
            cur_week_new_grow_aum_normal_hkd,
            cur_week_new_grow_aum_gold_hkd,
            cur_week_new_grow_aum_platinum_hkd,
            cur_week_new_grow_aum_diamond_hkd,
            cur_week_new_grow_aum_black_hkd,
            cur_week_cur_year_new_grow_avg_asset_hnw_hkd,
            pre_week_cur_year_new_grow_avg_asset_hnw_hkd,
            cur_week_cur_year_new_grow_avg_asset_normal_hkd,
            pre_week_cur_year_new_grow_avg_asset_normal_hkd,
            cur_week_cur_year_new_grow_avg_asset_gold_hkd,
            pre_week_cur_year_new_grow_avg_asset_gold_hkd,
            cur_week_cur_year_new_grow_avg_asset_platinum_hkd,
            pre_week_cur_year_new_grow_avg_asset_platinum_hkd,
            cur_week_cur_year_new_grow_avg_asset_diamond_hkd,
            pre_week_cur_year_new_grow_avg_asset_diamond_hkd,
            cur_week_cur_year_new_grow_avg_asset_black_hkd,
            pre_week_cur_year_new_grow_avg_asset_black_hkd,
            cur_year_new_grow_aum_hnw_us,
            pre_week_new_grow_asset_aum_hnw_us,
            cur_year_new_grow_aum_normal_us,
            cur_year_new_grow_aum_gold_us,
            cur_year_new_grow_aum_platinum_us,
            cur_year_new_grow_aum_diamond_us,
            cur_year_new_grow_aum_black_us,
            cur_week_new_grow_aum_normal_us,
            cur_week_new_grow_aum_gold_us,
            cur_week_new_grow_aum_platinum_us,
            cur_week_new_grow_aum_diamond_us,
            cur_week_new_grow_aum_black_us,
            cur_week_cur_year_new_grow_avg_asset_hnw_us,
            pre_week_cur_year_new_grow_avg_asset_hnw_us,
            cur_week_cur_year_new_grow_avg_asset_normal_us,
            pre_week_cur_year_new_grow_avg_asset_normal_us,
            cur_week_cur_year_new_grow_avg_asset_gold_us,
            pre_week_cur_year_new_grow_avg_asset_gold_us,
            cur_week_cur_year_new_grow_avg_asset_platinum_us,
            pre_week_cur_year_new_grow_avg_asset_platinum_us,
            cur_week_cur_year_new_grow_avg_asset_diamond_us,
            pre_week_cur_year_new_grow_avg_asset_diamond_us,
            cur_week_cur_year_new_grow_avg_asset_black_us,
            pre_week_cur_year_new_grow_avg_asset_black_us,
            # 流失量统计
            cur_year_loss_hnw_counts,
            pre_week_loss_hnw_counts,
            cur_year_loss_normal_counts,
            cur_year_loss_gold_counts,
            cur_year_loss_platinum_counts,
            cur_year_loss_diamond_counts,
            cur_year_loss_black_counts,
            cur_week_grow_loss_normal_counts,
            cur_week_grow_loss_gold_counts,
            cur_week_grow_loss_platinum_counts,
            cur_week_grow_loss_diamond_counts,
            cur_week_grow_loss_black_counts,
            cur_year_loss_hnw_hkd,
            pre_week_loss_hnw_hkd,
            cur_year_loss_normal_hkd,
            cur_year_loss_gold_hkd,
            cur_year_loss_platinum_hkd,
            cur_year_loss_diamond_hkd,
            cur_year_loss_black_hkd,
            cur_week_loss_grow_normal_hkd,
            cur_week_loss_grow_gold_hkd,
            cur_week_loss_grow_platinum_hkd,
            cur_week_loss_grow_diamond_hkd,
            cur_week_loss_grow_black_hkd,
            cur_year_loss_avg_hnw_aum_hkd,
            pre_week_cur_year_loss_avg_hnw_aum_hkd,
            cur_year_loss_avg_normal_aum_hkd,
            pre_week_cur_year_loss_avg_normal_aum_hkd,
            cur_year_loss_avg_gold_aum_hkd,
            pre_week_cur_year_loss_avg_gold_aum_hkd,
            cur_year_loss_avg_platinum_aum_hkd,
            pre_week_cur_year_loss_avg_platinum_aum_hkd,
            cur_year_loss_avg_diamond_aum_hkd,
            pre_week_cur_year_loss_avg_diamond_aum_hkd,
            cur_year_loss_avg_black_aum_hkd,
            pre_week_cur_year_loss_avg_black_aum_hkd,
            cur_year_loss_hnw_us,
            pre_week_loss_hnw_us,
            cur_year_loss_normal_us,
            cur_year_loss_gold_us,
            cur_year_loss_platinum_us,
            cur_year_loss_diamond_us,
            cur_year_loss_black_us,
            cur_week_loss_grow_normal_us,
            cur_week_loss_grow_gold_us,
            cur_week_loss_grow_platinum_us,
            cur_week_loss_grow_diamond_us,
            cur_week_loss_grow_black_us,
            cur_year_loss_avg_hnw_aum_us,
            pre_week_cur_year_loss_avg_hnw_aum_us,
            cur_year_loss_avg_normal_aum_us,
            pre_week_cur_year_loss_avg_normal_aum_us,
            cur_year_loss_avg_gold_aum_us,
            pre_week_cur_year_loss_avg_gold_aum_us,
            cur_year_loss_avg_platinum_aum_us,
            pre_week_cur_year_loss_avg_platinum_aum_us,
            cur_year_loss_avg_diamond_aum_us,
            pre_week_cur_year_loss_avg_diamond_aum_us,
            cur_year_loss_avg_black_aum_us,
            pre_week_cur_year_loss_avg_hnw_aum_us,
            cur_fx_rate,
        ) = ads_hook.get_first(sql_content.format(cur_date))
        worksheet_net[f"A{row + 1}"] = item.strftime("%Y/%m/%d")
        _mark_value(
            worksheet_net[f"C{row + 1}"],
            cur_year_net_new_grow_hnw_counts,
            pre_week_net_new_grow_hnw_counts,
        )

        _mark_value(
            worksheet_net[f"D{row + 1}"],
            cur_year_net_new_grow_normal_counts,
            flag=False,
        )
        _mark_value(
            worksheet_net[f"D{row + 2}"], cur_year_net_new_grow_gold_counts, flag=False
        )
        _mark_value(
            worksheet_net[f"D{row + 3}"],
            cur_year_net_new_grow_platinum_counts,
            flag=False,
        )
        _mark_value(
            worksheet_net[f"D{row + 4}"],
            cur_year_net_new_grow_diamond_counts,
            flag=False,
        )
        _mark_value(
            worksheet_net[f"D{row + 5}"], cur_year_net_new_grow_black_counts, flag=False
        )

        _mark_value(worksheet_net[f"E{row + 1}"], cur_week_net_new_grow_normal_counts)
        _mark_value(worksheet_net[f"E{row + 2}"], cur_week_net_new_grow_gold_counts)
        _mark_value(worksheet_net[f"E{row + 3}"], cur_week_net_new_grow_platinum_counts)
        _mark_value(worksheet_net[f"E{row + 4}"], cur_week_net_new_grow_diamond_counts)
        _mark_value(worksheet_net[f"E{row + 5}"], cur_week_net_new_grow_black_counts)

        _mark_value(
            worksheet_net[f"F{row + 1}"],
            cur_year_net_new_grow_aum_hnw_hkd,
            pre_week_net_new_grow_asset_aum_hnw_hkd,
        )

        _mark_value(
            worksheet_net[f"G{row + 1}"],
            cur_year_net_new_grow_aum_normal_hkd,
            flag=False,
        )
        _mark_value(
            worksheet_net[f"G{row + 2}"], cur_year_net_new_grow_aum_gold_hkd, flag=False
        )
        _mark_value(
            worksheet_net[f"G{row + 3}"],
            cur_year_net_new_grow_aum_platinum_hkd,
            flag=False,
        )
        _mark_value(
            worksheet_net[f"G{row + 4}"],
            cur_year_net_new_grow_aum_diamond_hkd,
            flag=False,
        )
        _mark_value(
            worksheet_net[f"G{row + 5}"],
            cur_year_net_new_grow_aum_black_hkd,
            flag=False,
        )

        _mark_value(worksheet_net[f"H{row + 1}"], cur_week_net_new_grow_aum_normal_hkd)
        _mark_value(worksheet_net[f"H{row + 2}"], cur_week_net_new_grow_aum_gold_hkd)
        _mark_value(
            worksheet_net[f"H{row + 3}"], cur_week_net_new_grow_aum_platinum_hkd
        )
        _mark_value(worksheet_net[f"H{row + 4}"], cur_week_net_new_grow_aum_diamond_hkd)
        _mark_value(worksheet_net[f"H{row + 5}"], cur_week_net_new_grow_aum_black_hkd)

        _mark_value(
            worksheet_net[f"I{row + 1}"],
            cur_week_cur_year_net_new_grow_avg_asset_hnw_hkd,
            pre_week_cur_year_net_new_grow_avg_asset_hnw_hkd,
        )

        _mark_value(
            worksheet_net[f"J{row + 1}"],
            cur_week_cur_year_net_new_grow_avg_asset_normal_hkd,
            pre_week_cur_year_net_new_grow_avg_asset_normal_hkd,
        )
        _mark_value(
            worksheet_net[f"J{row + 2}"],
            cur_week_cur_year_net_new_grow_avg_asset_gold_hkd,
            pre_week_cur_year_net_new_grow_avg_asset_gold_hkd,
        )
        _mark_value(
            worksheet_net[f"J{row + 3}"],
            cur_week_cur_year_net_new_grow_avg_asset_platinum_hkd,
            pre_week_cur_year_net_new_grow_avg_asset_platinum_hkd,
        )
        _mark_value(
            worksheet_net[f"J{row + 4}"],
            cur_week_cur_year_net_new_grow_avg_asset_diamond_hkd,
            pre_week_cur_year_net_new_grow_avg_asset_diamond_hkd,
        )
        _mark_value(
            worksheet_net[f"J{row + 5}"],
            cur_week_cur_year_net_new_grow_avg_asset_black_hkd,
            pre_week_cur_year_net_new_grow_avg_asset_black_hkd,
        )

        _mark_value(
            worksheet_net[f"K{row + 1}"],
            cur_year_net_new_grow_aum_hnw_us,
            pre_week_net_new_grow_asset_aum_hnw_us,
        )

        _mark_value(
            worksheet_net[f"L{row + 1}"],
            cur_year_net_new_grow_aum_normal_us,
            flag=False,
        )
        _mark_value(
            worksheet_net[f"L{row + 2}"], cur_year_net_new_grow_aum_gold_us, flag=False
        )
        _mark_value(
            worksheet_net[f"L{row + 3}"],
            cur_year_net_new_grow_aum_platinum_us,
            flag=False,
        )
        _mark_value(
            worksheet_net[f"L{row + 4}"],
            cur_year_net_new_grow_aum_diamond_us,
            flag=False,
        )
        _mark_value(
            worksheet_net[f"L{row + 5}"], cur_year_net_new_grow_aum_black_us, flag=False
        )

        _mark_value(worksheet_net[f"M{row + 1}"], cur_week_net_new_grow_aum_normal_us)
        _mark_value(worksheet_net[f"M{row + 2}"], cur_week_net_new_grow_aum_gold_us)
        _mark_value(worksheet_net[f"M{row + 3}"], cur_week_net_new_grow_aum_platinum_us)
        _mark_value(worksheet_net[f"M{row + 4}"], cur_week_net_new_grow_aum_diamond_us)
        _mark_value(worksheet_net[f"M{row + 5}"], cur_week_net_new_grow_aum_black_us)

        _mark_value(
            worksheet_net[f"N{row + 1}"],
            cur_week_cur_year_net_new_grow_avg_asset_hnw_us,
            pre_week_cur_year_net_new_grow_avg_asset_hnw_us,
        )

        _mark_value(
            worksheet_net[f"O{row + 1}"],
            cur_week_cur_year_net_new_grow_avg_asset_normal_us,
            pre_week_cur_year_net_new_grow_avg_asset_normal_us,
        )
        _mark_value(
            worksheet_net[f"O{row + 2}"],
            cur_week_cur_year_net_new_grow_avg_asset_gold_us,
            pre_week_cur_year_net_new_grow_avg_asset_gold_us,
        )
        _mark_value(
            worksheet_net[f"O{row + 3}"],
            cur_week_cur_year_net_new_grow_avg_asset_platinum_us,
            pre_week_cur_year_net_new_grow_avg_asset_platinum_us,
        )
        _mark_value(
            worksheet_net[f"O{row + 4}"],
            cur_week_cur_year_net_new_grow_avg_asset_diamond_us,
            pre_week_cur_year_net_new_grow_avg_asset_diamond_us,
        )
        _mark_value(
            worksheet_net[f"O{row + 5}"],
            cur_week_cur_year_net_new_grow_avg_asset_black_us,
            pre_week_cur_year_net_new_grow_avg_asset_black_us,
        )

        worksheet_net[f"P{row + 1}"] = "{:.6f}".format(float(cur_fx_rate))

        # 增长数据
        worksheet_grow[f"A{row + 1}"] = item.strftime("%Y/%m/%d")
        _mark_value(
            worksheet_grow[f"C{row + 1}"],
            cur_year_new_grow_hnw_counts,
            pre_week_new_grow_hnw_counts,
        )

        _mark_value(
            worksheet_grow[f"D{row + 1}"], cur_year_new_grow_normal_counts, flag=False
        )
        _mark_value(
            worksheet_grow[f"D{row + 2}"], cur_year_new_grow_gold_counts, flag=False
        )
        _mark_value(
            worksheet_grow[f"D{row + 3}"], cur_year_new_grow_platinum_counts, flag=False
        )
        _mark_value(
            worksheet_grow[f"D{row + 4}"], cur_year_new_grow_diamond_counts, flag=False
        )
        _mark_value(
            worksheet_grow[f"D{row + 5}"], cur_year_new_grow_black_counts, flag=False
        )

        _mark_value(worksheet_grow[f"E{row + 1}"], cur_week_new_grow_normal_counts)
        _mark_value(worksheet_grow[f"E{row + 2}"], cur_week_new_grow_gold_counts)
        _mark_value(worksheet_grow[f"E{row + 3}"], cur_week_new_grow_platinum_counts)
        _mark_value(worksheet_grow[f"E{row + 4}"], cur_week_new_grow_diamond_counts)
        _mark_value(worksheet_grow[f"E{row + 5}"], cur_week_new_grow_black_counts)

        _mark_value(
            worksheet_grow[f"F{row + 1}"],
            cur_year_new_grow_aum_hnw_hkd,
            pre_week_new_grow_asset_aum_hnw_hkd,
        )

        _mark_value(
            worksheet_grow[f"G{row + 1}"], cur_year_new_grow_aum_normal_hkd, flag=False
        )
        _mark_value(
            worksheet_grow[f"G{row + 2}"], cur_year_new_grow_aum_gold_hkd, flag=False
        )
        _mark_value(
            worksheet_grow[f"G{row + 3}"],
            cur_year_new_grow_aum_platinum_hkd,
            flag=False,
        )
        _mark_value(
            worksheet_grow[f"G{row + 4}"], cur_year_new_grow_aum_diamond_hkd, flag=False
        )
        _mark_value(
            worksheet_grow[f"G{row + 5}"], cur_year_new_grow_aum_black_hkd, flag=False
        )

        _mark_value(worksheet_grow[f"H{row + 1}"], cur_week_new_grow_aum_normal_hkd)
        _mark_value(worksheet_grow[f"H{row + 2}"], cur_week_new_grow_aum_gold_hkd)
        _mark_value(worksheet_grow[f"H{row + 3}"], cur_week_new_grow_aum_platinum_hkd)
        _mark_value(worksheet_grow[f"H{row + 4}"], cur_week_new_grow_aum_diamond_hkd)
        _mark_value(worksheet_grow[f"H{row + 5}"], cur_week_new_grow_aum_black_hkd)

        _mark_value(
            worksheet_grow[f"I{row + 1}"],
            cur_week_cur_year_new_grow_avg_asset_hnw_hkd,
            pre_week_cur_year_new_grow_avg_asset_hnw_hkd,
        )

        _mark_value(
            worksheet_grow[f"J{row + 1}"],
            cur_week_cur_year_new_grow_avg_asset_normal_hkd,
            pre_week_cur_year_new_grow_avg_asset_normal_hkd,
        )
        _mark_value(
            worksheet_grow[f"J{row + 2}"],
            cur_week_cur_year_new_grow_avg_asset_gold_hkd,
            pre_week_cur_year_new_grow_avg_asset_gold_hkd,
        )
        _mark_value(
            worksheet_grow[f"J{row + 3}"],
            cur_week_cur_year_new_grow_avg_asset_platinum_hkd,
            pre_week_cur_year_new_grow_avg_asset_platinum_hkd,
        )
        _mark_value(
            worksheet_grow[f"J{row + 4}"],
            cur_week_cur_year_new_grow_avg_asset_diamond_hkd,
            pre_week_cur_year_new_grow_avg_asset_diamond_hkd,
        )
        _mark_value(
            worksheet_grow[f"J{row + 5}"],
            cur_week_cur_year_new_grow_avg_asset_black_hkd,
            pre_week_cur_year_new_grow_avg_asset_black_hkd,
        )

        _mark_value(
            worksheet_grow[f"K{row + 1}"],
            cur_year_new_grow_aum_hnw_us,
            pre_week_new_grow_asset_aum_hnw_us,
        )

        _mark_value(
            worksheet_grow[f"L{row + 1}"], cur_year_new_grow_aum_normal_us, flag=False
        )
        _mark_value(
            worksheet_grow[f"L{row + 2}"], cur_year_new_grow_aum_gold_us, flag=False
        )
        _mark_value(
            worksheet_grow[f"L{row + 3}"], cur_year_new_grow_aum_platinum_us, flag=False
        )
        _mark_value(
            worksheet_grow[f"L{row + 4}"], cur_year_new_grow_aum_diamond_us, flag=False
        )
        _mark_value(
            worksheet_grow[f"L{row + 5}"], cur_year_new_grow_aum_black_us, flag=False
        )

        _mark_value(worksheet_grow[f"M{row + 1}"], cur_week_new_grow_aum_normal_us)
        _mark_value(worksheet_grow[f"M{row + 2}"], cur_week_new_grow_aum_gold_us)
        _mark_value(worksheet_grow[f"M{row + 3}"], cur_week_new_grow_aum_platinum_us)
        _mark_value(worksheet_grow[f"M{row + 4}"], cur_week_new_grow_aum_diamond_us)
        _mark_value(worksheet_grow[f"M{row + 5}"], cur_week_new_grow_aum_black_us)

        _mark_value(
            worksheet_grow[f"N{row + 1}"],
            cur_week_cur_year_new_grow_avg_asset_hnw_us,
            pre_week_cur_year_new_grow_avg_asset_hnw_us,
        )

        _mark_value(
            worksheet_grow[f"O{row + 1}"],
            cur_week_cur_year_new_grow_avg_asset_normal_us,
            pre_week_cur_year_new_grow_avg_asset_normal_us,
        )
        _mark_value(
            worksheet_grow[f"O{row + 2}"],
            cur_week_cur_year_new_grow_avg_asset_gold_us,
            pre_week_cur_year_new_grow_avg_asset_gold_us,
        )
        _mark_value(
            worksheet_grow[f"O{row + 3}"],
            cur_week_cur_year_new_grow_avg_asset_platinum_us,
            pre_week_cur_year_new_grow_avg_asset_platinum_us,
        )
        _mark_value(
            worksheet_grow[f"O{row + 4}"],
            cur_week_cur_year_new_grow_avg_asset_diamond_us,
            pre_week_cur_year_new_grow_avg_asset_diamond_us,
        )
        _mark_value(
            worksheet_grow[f"O{row + 5}"],
            cur_week_cur_year_new_grow_avg_asset_black_us,
            pre_week_cur_year_new_grow_avg_asset_black_us,
        )

        worksheet_grow[f"P{row + 1}"] = "{:.6f}".format(float(cur_fx_rate))

        # 流失数据
        _mark_value(
            worksheet_loss[f"C{row + 1}"],
            cur_year_loss_hnw_counts,
            pre_week_loss_hnw_counts,
        )

        _mark_value(
            worksheet_loss[f"D{row + 1}"], cur_year_loss_normal_counts, flag=False
        )
        _mark_value(
            worksheet_loss[f"D{row + 2}"], cur_year_loss_gold_counts, flag=False
        )
        _mark_value(
            worksheet_loss[f"D{row + 3}"], cur_year_loss_platinum_counts, flag=False
        )
        _mark_value(
            worksheet_loss[f"D{row + 4}"], cur_year_loss_diamond_counts, flag=False
        )
        _mark_value(
            worksheet_loss[f"D{row + 5}"], cur_year_loss_black_counts, flag=False
        )

        _mark_value(worksheet_loss[f"E{row + 1}"], cur_week_grow_loss_normal_counts)
        _mark_value(worksheet_loss[f"E{row + 2}"], cur_week_grow_loss_gold_counts)
        _mark_value(worksheet_loss[f"E{row + 3}"], cur_week_grow_loss_platinum_counts)
        _mark_value(worksheet_loss[f"E{row + 4}"], cur_week_grow_loss_diamond_counts)
        _mark_value(worksheet_loss[f"E{row + 5}"], cur_week_grow_loss_black_counts)

        _mark_value(
            worksheet_loss[f"F{row + 1}"], cur_year_loss_hnw_hkd, pre_week_loss_hnw_hkd
        )

        _mark_value(worksheet_loss[f"G{row + 1}"], cur_year_loss_normal_hkd, flag=False)
        _mark_value(worksheet_loss[f"G{row + 2}"], cur_year_loss_gold_hkd, flag=False)
        _mark_value(
            worksheet_loss[f"G{row + 3}"], cur_year_loss_platinum_hkd, flag=False
        )
        _mark_value(
            worksheet_loss[f"G{row + 4}"], cur_year_loss_diamond_hkd, flag=False
        )
        _mark_value(worksheet_loss[f"G{row + 5}"], cur_year_loss_black_hkd, flag=False)

        _mark_value(worksheet_loss[f"H{row + 1}"], cur_week_loss_grow_normal_hkd)
        _mark_value(worksheet_loss[f"H{row + 2}"], cur_week_loss_grow_gold_hkd)
        _mark_value(worksheet_loss[f"H{row + 3}"], cur_week_loss_grow_platinum_hkd)
        _mark_value(worksheet_loss[f"H{row + 4}"], cur_week_loss_grow_diamond_hkd)
        _mark_value(worksheet_loss[f"H{row + 5}"], cur_week_loss_grow_black_hkd)

        _mark_value(
            worksheet_loss[f"I{row + 1}"],
            cur_year_loss_avg_hnw_aum_hkd,
            pre_week_cur_year_loss_avg_hnw_aum_hkd,
        )

        _mark_value(
            worksheet_loss[f"J{row + 1}"],
            cur_year_loss_avg_normal_aum_hkd,
            pre_week_cur_year_loss_avg_normal_aum_hkd,
        )
        _mark_value(
            worksheet_loss[f"J{row + 2}"],
            cur_year_loss_avg_gold_aum_hkd,
            pre_week_cur_year_loss_avg_gold_aum_hkd,
        )
        _mark_value(
            worksheet_loss[f"J{row + 3}"],
            cur_year_loss_avg_platinum_aum_hkd,
            pre_week_cur_year_loss_avg_platinum_aum_hkd,
        )
        _mark_value(
            worksheet_loss[f"J{row + 4}"],
            cur_year_loss_avg_diamond_aum_hkd,
            pre_week_cur_year_loss_avg_diamond_aum_hkd,
        )
        _mark_value(
            worksheet_loss[f"J{row + 5}"],
            cur_year_loss_avg_black_aum_hkd,
            pre_week_cur_year_loss_avg_black_aum_hkd,
        )

        _mark_value(
            worksheet_loss[f"K{row + 1}"], cur_year_loss_hnw_us, pre_week_loss_hnw_us
        )

        _mark_value(worksheet_loss[f"L{row + 1}"], cur_year_loss_normal_us, flag=False)
        _mark_value(worksheet_loss[f"L{row + 2}"], cur_year_loss_gold_us, flag=False)
        _mark_value(
            worksheet_loss[f"L{row + 3}"], cur_year_loss_platinum_us, flag=False
        )
        _mark_value(worksheet_loss[f"L{row + 4}"], cur_year_loss_diamond_us, flag=False)
        _mark_value(worksheet_loss[f"L{row + 5}"], cur_year_loss_black_us, flag=False)

        _mark_value(worksheet_loss[f"M{row + 1}"], cur_week_loss_grow_normal_us)
        _mark_value(worksheet_loss[f"M{row + 2}"], cur_week_loss_grow_gold_us)
        _mark_value(worksheet_loss[f"M{row + 3}"], cur_week_loss_grow_platinum_us)
        _mark_value(worksheet_loss[f"M{row + 4}"], cur_week_loss_grow_diamond_us)
        _mark_value(worksheet_loss[f"M{row + 5}"], cur_week_loss_grow_black_us)

        _mark_value(
            worksheet_loss[f"N{row + 1}"],
            cur_year_loss_avg_hnw_aum_us,
            pre_week_cur_year_loss_avg_hnw_aum_us,
        )

        _mark_value(
            worksheet_loss[f"O{row + 1}"],
            cur_year_loss_avg_normal_aum_us,
            pre_week_cur_year_loss_avg_normal_aum_us,
        )
        _mark_value(
            worksheet_loss[f"O{row + 2}"],
            cur_year_loss_avg_gold_aum_us,
            pre_week_cur_year_loss_avg_gold_aum_us,
        )
        _mark_value(
            worksheet_loss[f"O{row + 3}"],
            cur_year_loss_avg_platinum_aum_us,
            pre_week_cur_year_loss_avg_platinum_aum_us,
        )
        _mark_value(
            worksheet_loss[f"O{row + 4}"],
            cur_year_loss_avg_diamond_aum_us,
            pre_week_cur_year_loss_avg_diamond_aum_us,
        )
        _mark_value(
            worksheet_loss[f"O{row + 5}"],
            cur_year_loss_avg_black_aum_us,
            pre_week_cur_year_loss_avg_hnw_aum_us,
        )

        worksheet_loss[f"P{row + 1}"] = "{:.6f}".format(float(cur_fx_rate))
        row += 5
    workbook.save(result_file_path)


def generate_operation_hnw_stats(p_curr_end_date: date, result_file_path: str):
    """生成高客相关报表结果文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/operation_explore/operation_hnw_stats_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    date_fmt = "%Y-%m-%d"

    sql_query = get_file_content("sql/ads/operation_explore/operation_hnw_stats.sql")

    row_num = 2
    for p_group_by_cat in (1, 0):
        for (
            cat,
            curr_hnw_num,
            curr_year_new_hnw_num,
            new_hnw_change_rate,
            curr_asset_hkd,
            asset_change_rate,
            curr_year_deposit_hkd,
            deposit_rate_of_all,
            deposit_change_rate,
            curr_year_revenue_hkd,
            year_revenue_change_rate,
            curr_quarter_revenue_hkd,
            quarter_revenue_change_rate,
            curr_month_revenue_hkd,
            month_revenue_change_rate,
        ) in ads_hook.get_records(
            sql_query.format(
                p_curr_end_date=p_curr_end_date.strftime(date_fmt),
                p_group_by_cat=p_group_by_cat,
            )
        ):
            worksheet[f"B{row_num}"].value = curr_hnw_num
            worksheet[f"C{row_num}"].value = curr_year_new_hnw_num
            worksheet[f"D{row_num}"].value = _to_float(new_hnw_change_rate)
            worksheet[f"E{row_num}"].value = _to_float(curr_asset_hkd)
            worksheet[f"F{row_num}"].value = _to_float(asset_change_rate)
            worksheet[f"G{row_num}"].value = _to_float(curr_year_deposit_hkd)
            worksheet[f"H{row_num}"].value = _to_float(deposit_rate_of_all)
            worksheet[f"I{row_num}"].value = _to_float(deposit_change_rate)
            worksheet[f"J{row_num}"].value = _to_float(curr_year_revenue_hkd)
            worksheet[f"K{row_num}"].value = _to_float(year_revenue_change_rate)
            worksheet[f"L{row_num}"].value = _to_float(curr_quarter_revenue_hkd)
            worksheet[f"M{row_num}"].value = _to_float(quarter_revenue_change_rate)
            worksheet[f"N{row_num}"].value = _to_float(curr_month_revenue_hkd)
            worksheet[f"O{row_num}"].value = _to_float(month_revenue_change_rate)
            row_num += 1

    workbook.save(result_file_path)


def generate_revenue_aum_per_aecode(result_file_path, p_report_date):
    """生成客服分AECode营收AUM结果文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/customer_service/revenue_aum_per_aecode_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    date_fmt = "%Y-%m-%d"

    # 1. aecode
    sql_per_aecode = get_file_content(
        "sql/ads/customer_service/revenue_aum_per_aecode.sql"
    )
    sql_per_aecode = sql_per_aecode.format(
        p_stats_date=p_report_date.strftime(date_fmt)
    )
    worksheet = workbook["AECode"]

    row_num = 2
    for (
        ae_code,
        ytd_trade_nonwealth_commission_hkd,
        ytd_debit_interest_after_deduct_hkd,
        current_balance_hkd,
        current_wealth_market_value_hkd,
        current_market_value_hkd,
        current_asset_hkd,
    ) in ads_hook.get_records(sql_per_aecode):
        worksheet[f"A{row_num}"] = ae_code
        worksheet[f"B{row_num}"] = _to_float(ytd_trade_nonwealth_commission_hkd)
        worksheet[f"C{row_num}"] = _to_float(ytd_debit_interest_after_deduct_hkd)
        worksheet[f"D{row_num}"] = _to_float(current_balance_hkd)
        worksheet[f"E{row_num}"] = _to_float(current_wealth_market_value_hkd)
        worksheet[f"F{row_num}"] = _to_float(current_market_value_hkd)
        worksheet[f"G{row_num}"] = _to_float(current_asset_hkd)

        row_num += 1

    # 2. summary
    sql_summary = get_file_content("sql/ads/customer_service/revenue_aum_summary.sql")
    worksheet = workbook["汇总"]

    for stats_type in ("current", "prev_year", "prev_week"):
        if stats_type == "current":
            p_stats_date = p_report_date
            column_name = "B"
        elif stats_type == "prev_year":
            p_stats_date = p_report_date - timedelta(days=365)
            column_name = "D"
        else:
            p_stats_date = p_report_date - timedelta(days=7)
            column_name = "G"

        (
            total_asset_hkd,
            fosun_group_asset_hkd,
            client_asset_hkd,
            client_balance_hkd,
            client_nonwealth_market_value_hkd,
            client_otcb_market_value_hkd,
            client_inner_stpd_market_value_hkd,
            client_outer_stpd_market_value_hkd,
            client_fund_market_value_hkd,
            client_mmf_market_value_hkd,
        ) = ads_hook.get_first(
            sql_summary.format(p_stats_date=p_stats_date.strftime(date_fmt))
        )
        worksheet[f"{column_name}2"] = _to_float(total_asset_hkd)
        worksheet[f"{column_name}3"] = _to_float(fosun_group_asset_hkd)
        worksheet[f"{column_name}4"] = _to_float(client_asset_hkd)
        worksheet[f"{column_name}8"] = _to_float(client_asset_hkd)
        worksheet[f"{column_name}9"] = _to_float(client_balance_hkd)
        worksheet[f"{column_name}10"] = _to_float(client_nonwealth_market_value_hkd)
        worksheet[f"{column_name}11"] = _to_float(client_otcb_market_value_hkd)
        worksheet[f"{column_name}12"] = _to_float(client_inner_stpd_market_value_hkd)
        worksheet[f"{column_name}13"] = _to_float(client_outer_stpd_market_value_hkd)
        worksheet[f"{column_name}14"] = _to_float(client_fund_market_value_hkd)
        worksheet[f"{column_name}15"] = _to_float(client_mmf_market_value_hkd)

    # 3. fosun group account
    worksheet = workbook["集团托管"]

    row_num = 2
    for account_no, name_english in ads_hook.get_records(
        "select account_no,name_english from ads.common_fosun_group_account"
    ):
        worksheet[f"A{row_num}"] = account_no
        worksheet[f"B{row_num}"] = name_english

        row_num += 1

    workbook.save(result_file_path)


def generate_open_account_summary(result_file_path, p_begin_date, p_end_date):
    """生成月度开户数统计结果文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/customer_service/open_account_summary_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Sheet1"]

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")
    date_fmt = "%Y-%m-%d"
    sql_query = get_file_content("sql/ads/customer_service/open_account_summary.sql")
    sql_query = sql_query.format(
        p_begin_date=p_begin_date.strftime(date_fmt),
        p_end_date=p_end_date.strftime(date_fmt),
    )

    row_num = 2
    for (
        client_type_desc,
        all_open_num,
        all_aml_high_num,
        all_aml_middle_num,
        all_aml_low_num,
        all_aml_na_num,
        entrusted_open_num,
    ) in ads_hook.get_records(sql_query):
        worksheet[f"A{row_num}"] = client_type_desc
        worksheet[f"B{row_num}"] = all_open_num
        worksheet[f"C{row_num}"] = all_aml_high_num
        worksheet[f"D{row_num}"] = all_aml_middle_num
        worksheet[f"E{row_num}"] = all_aml_low_num
        worksheet[f"F{row_num}"] = all_aml_na_num
        worksheet[f"G{row_num}"] = entrusted_open_num

        row_num += 1

    workbook.save(result_file_path)




def _fill_cell(worksheet, cell, val, is_rate, use_float_format):
    border_side = openpyxl.styles.Side(style="thin", color="FF000000")
    border = openpyxl.styles.Border(
        left=border_side, right=border_side, top=border_side, bottom=border_side
    )

    alignment = openpyxl.styles.Alignment(horizontal="general", vertical="center")

    # 跳过占位
    old_value = worksheet[cell].value
    if old_value is not None and old_value == "/":
        worksheet[cell].border = border
        worksheet[cell].alignment = alignment
        return True

    # 写入单元格
    if is_rate and val == 0.0:
        worksheet[cell].value = "/"
        worksheet[cell].style = "Normal"
    elif is_rate or use_float_format:
        worksheet[cell].value = val
    else:
        worksheet[cell].value = int(val)
        worksheet[cell].style = "Normal"

    worksheet[cell].border = border
    worksheet[cell].alignment = alignment

    return False


def generate_manage_analysis_fosun_group_asset(rpt_date: date, result_file_path: str):
    """生成集团资产托管统计结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/manage_analysis/fosun_group_asset_template.xlsx",
    )

    date_fmt = "%Y-%m-%d"
    sql = get_file_content("sql/ads/manage_analysis/fosun_group_asset.sql")
    sql = sql.format(p_rpt_date=rpt_date.strftime(date_fmt))

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    row_num = 2
    for (
        account_no,
        name_english,
        name_chinese,
        ae_code,
        open_date,
        asset,
    ) in ads_hook.get_records(sql):
        worksheet[f"A{row_num}"] = account_no
        worksheet[f"B{row_num}"] = name_english
        worksheet[f"C{row_num}"] = name_chinese
        worksheet[f"D{row_num}"] = ae_code
        worksheet[f"E{row_num}"] = _to_date(open_date)
        worksheet[f"F{row_num}"] = _to_float(asset)

        row_num += 1

    workbook.save(result_file_path)


def generate_channel_business_daily_report(rpt_date: date, result_file_path: str):
    """生成渠道部每日报表结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/channel_business/channel_business_daily_report_template.xlsx",
    )
    work_book = openpyxl.load_workbook(excel_template)

    sql_01_summary_01_prepare = get_splitted_sql(
        "sql/ads/channel_business/channel_business_daily_report_01_summary_01_prepare.sql"
    )
    sql_01_summary_02_compute = get_splitted_sql(
        "sql/ads/channel_business/channel_business_daily_report_01_summary_02_compute.sql"
    )
    sql_01_summary_03_result = get_file_content(
        "sql/ads/channel_business/channel_business_daily_report_01_summary_03_result.sql"
    )
    sql_01_summary_04_clear = get_splitted_sql(
        "sql/ads/channel_business/channel_business_daily_report_01_summary_04_clear.sql"
    )
    sql_02_trade = get_file_content(
        "sql/ads/channel_business/channel_business_daily_report_02_trade.sql"
    )
    sql_03_client = get_file_content(
        "sql/ads/channel_business/channel_business_daily_report_03_client.sql"
    )

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    # 1. 汇总数据
    worksheet_summary = work_book["汇总数据"]
    # 1.1 创建结果临时表
    ads_hook.run(sql_01_summary_01_prepare)

    # 1.2 计算指标
    for period in ("Y", "M", "W"):
        if period == "Y":
            curr_end_date = rpt_date
            curr_begin_date = date(curr_end_date.year, 1, 1)
            prev_end_date = rpt_date - timedelta(days=365)
            if prev_end_date.year == rpt_date.year:
                prev_end_date = date(rpt_date.year - 1, 12, 31)
            prev_begin_date = date(prev_end_date.year, 1, 1)
        elif period == "M":
            curr_end_date = rpt_date
            curr_begin_date = date(curr_end_date.year, curr_end_date.month, 1)
            prev_end_date = rpt_date - timedelta(days=31)
            prev_begin_date = date(prev_end_date.year, prev_end_date.month, 1)
        elif period == "W":
            curr_begin_date = (
                rpt_date - timedelta(days=rpt_date.weekday()) - timedelta(days=3)
            )  # 上周五
            curr_end_date = curr_begin_date + timedelta(days=6)
            prev_end_date = curr_end_date - timedelta(days=7)
            prev_begin_date = curr_begin_date - timedelta(days=7)
        else:
            return

        curr_begin_date = curr_begin_date.strftime(date_fmt)
        curr_end_date = curr_end_date.strftime(date_fmt)
        prev_begin_date = prev_begin_date.strftime(date_fmt)
        prev_end_date = prev_end_date.strftime(date_fmt)

        for sql in sql_01_summary_02_compute:
            ads_hook.run(
                sql.format(
                    p_curr_begin_date=curr_begin_date,
                    p_curr_end_date=curr_end_date,
                    p_prev_begin_date=prev_begin_date,
                    p_prev_end_date=prev_end_date,
                    p_period_type=period,
                )
            )

    # 1.3 写出结果
    number_format_val = copy(worksheet_summary["G2"].number_format)
    number_format_rate = copy(worksheet_summary["I2"].number_format)

    row_num = 2
    for (
        result_type,
        level1_channel,
        level2_channel,
        level3_channel,
        biz_type,
        result_unit,
        curr_week_val,
        prev_week_val,
        week_rate,
        curr_month_val,
        prev_month_val,
        month_rate,
        curr_year_val,
        prev_year_val,
        year_rate,
    ) in ads_hook.get_records(sql_01_summary_03_result):
        (
            curr_week_val,
            prev_week_val,
            week_rate,
            curr_month_val,
            prev_month_val,
            month_rate,
            curr_year_val,
            prev_year_val,
            year_rate,
        ) = (
            float(curr_week_val),
            float(prev_week_val),
            float(week_rate),
            float(curr_month_val),
            float(prev_month_val),
            float(month_rate),
            float(curr_year_val),
            float(prev_year_val),
            float(year_rate),
        )

        val_is_int = result_unit == "/"

        worksheet_summary[f"A{row_num}"].value = result_type
        worksheet_summary[f"B{row_num}"].value = level1_channel
        worksheet_summary[f"C{row_num}"].value = level2_channel
        worksheet_summary[f"D{row_num}"].value = level3_channel
        worksheet_summary[f"E{row_num}"].value = biz_type
        worksheet_summary[f"F{row_num}"].value = result_unit

        if val_is_int:
            worksheet_summary[f"G{row_num}"].value = int(curr_week_val)
            worksheet_summary[f"G{row_num}"].style = "Normal"

            worksheet_summary[f"H{row_num}"].value = int(prev_week_val)
            worksheet_summary[f"H{row_num}"].style = "Normal"

            worksheet_summary[f"J{row_num}"].value = int(curr_month_val)
            worksheet_summary[f"J{row_num}"].style = "Normal"

            worksheet_summary[f"K{row_num}"].value = int(prev_month_val)
            worksheet_summary[f"K{row_num}"].style = "Normal"

            worksheet_summary[f"M{row_num}"].value = int(curr_year_val)
            worksheet_summary[f"M{row_num}"].style = "Normal"

            worksheet_summary[f"N{row_num}"].value = int(prev_year_val)
            worksheet_summary[f"N{row_num}"].style = "Normal"
        else:
            worksheet_summary[f"G{row_num}"].value = curr_week_val
            worksheet_summary[f"G{row_num}"].number_format = number_format_val

            worksheet_summary[f"H{row_num}"].value = prev_week_val
            worksheet_summary[f"H{row_num}"].number_format = number_format_val

            worksheet_summary[f"J{row_num}"].value = curr_month_val
            worksheet_summary[f"J{row_num}"].number_format = number_format_val

            worksheet_summary[f"K{row_num}"].value = prev_month_val
            worksheet_summary[f"K{row_num}"].number_format = number_format_val

            worksheet_summary[f"M{row_num}"].value = curr_year_val
            worksheet_summary[f"M{row_num}"].number_format = number_format_val

            worksheet_summary[f"N{row_num}"].value = prev_year_val
            worksheet_summary[f"N{row_num}"].number_format = number_format_val

        worksheet_summary[f"I{row_num}"].value = week_rate if week_rate != 0.0 else "/"
        worksheet_summary[f"I{row_num}"].number_format = number_format_rate

        worksheet_summary[f"L{row_num}"].value = (
            month_rate if month_rate != 0.0 else "/"
        )
        worksheet_summary[f"L{row_num}"].number_format = number_format_rate

        worksheet_summary[f"O{row_num}"].value = year_rate if year_rate != 0.0 else "/"
        worksheet_summary[f"O{row_num}"].number_format = number_format_rate

        row_num += 1

    # 1.4 清理临时表
    ads_hook.run(sql_01_summary_04_clear)

    # 2. 订单明细
    worksheet_trade = work_book["订单明细"]

    end_date = rpt_date
    begin_date = date(end_date.year, 1, 1)

    end_date = end_date.strftime(date_fmt)
    begin_date = begin_date.strftime(date_fmt)

    row_num = 2
    for (
        account_no,
        ae_code,
        level1_channel,
        level2_channel,
        level3_channel,
        open_date,
        is_open_wealth,
        is_pi,
        trade_date,
        biz_line,
        security_name,
        trade_type,
        currency_code,
        amount,
        to_maturity_days,
    ) in ads_hook.get_records(
        sql_02_trade.format(p_begin_date=begin_date, p_end_date=end_date)
    ):
        amount = float(amount)

        worksheet_trade[f"A{row_num}"].value = account_no
        worksheet_trade[f"B{row_num}"].value = ae_code
        worksheet_trade[f"C{row_num}"].value = level1_channel
        worksheet_trade[f"D{row_num}"].value = level2_channel
        worksheet_trade[f"E{row_num}"].value = level3_channel
        worksheet_trade[f"F{row_num}"].value = open_date
        worksheet_trade[f"G{row_num}"].value = is_open_wealth
        worksheet_trade[f"H{row_num}"].value = is_pi
        worksheet_trade[f"I{row_num}"].value = trade_date
        worksheet_trade[f"J{row_num}"].value = biz_line
        worksheet_trade[f"K{row_num}"].value = security_name
        worksheet_trade[f"L{row_num}"].value = trade_type
        worksheet_trade[f"M{row_num}"].value = currency_code
        worksheet_trade[f"N{row_num}"].value = amount
        worksheet_trade[f"O{row_num}"].value = to_maturity_days

        row_num += 1

    # 3. 客户明细
    worksheet_client = work_book["客户明细"]

    row_num = 2
    for (
        account_no,
        ae_code,
        level1_channel,
        level2_channel,
        level3_channel,
        open_date,
        is_open_wealth,
        is_pi,
    ) in ads_hook.get_records(
        sql_03_client.format(p_begin_date=begin_date, p_end_date=end_date)
    ):
        worksheet_client[f"A{row_num}"].value = account_no
        worksheet_client[f"B{row_num}"].value = ae_code
        worksheet_client[f"C{row_num}"].value = level1_channel
        worksheet_client[f"D{row_num}"].value = level2_channel
        worksheet_client[f"E{row_num}"].value = level3_channel
        worksheet_client[f"F{row_num}"].value = open_date
        worksheet_client[f"G{row_num}"].value = is_open_wealth
        worksheet_client[f"H{row_num}"].value = is_pi

        row_num += 1

    work_book.save(result_file_path)


def generate_payoneer_monthly_asset_trade_movement_report(
    p_report_date: date,
    asset_file_path: str,
    trade_file_path: str,
    movement_file_path: str,
):
    """生成派安盈交易/入金/AUM数据报表Excel文件"""

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    asset_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/payoneer_asset_template.xlsx",
    )
    asset_workbook = openpyxl.load_workbook(asset_template)
    asset_summary_worksheet = asset_workbook["汇总"]
    asset_product_worksheet = asset_workbook["分产品"]

    asset_summary_sql = """select
    a.asof_date,a.currency_code,
    sum(case when a.biz_line_key like 'WEALTH|FUND%' then a.asset else 0 end) as fund,
    sum(case when a.biz_line_key like 'WEALTH|OTCB%' then a.asset else 0 end) as bond,
    sum(case when a.biz_line_key like 'WEALTH|STPD%' then a.asset else 0 end) as note,
    sum(case when a.biz_line_key like 'BASE|BALANCE%' then a.asset else 0 end) as balance,
    sum(a.asset) as asset
from dws.dws_account_asset_daily_by_biz_currency a
inner join dim.dim_account p
    on a.account_no=p.account_no
where
    a.asof_date between '2023-01-01' and '{p_report_date}'
    and p.default_ae_code='W300'
group by a.asof_date,a.currency_code
order by a.asof_date desc,a.currency_code"""

    asset_product_sql = """select
    h.asof_date,s.exchange_code,s.security_code,
    any(case
        when s.name_chinese<>'' then s.name_chinese
        else s.name_english
    end) as security_name,
    any(b.level2_name) as security_type,
    any(h.currency_code) as currency_code,
    sum(h.current_market_value) as market_value
from dwd.dwd_daily_holding h
inner join dim.dim_account a
    on h.account_no=a.account_no
inner join dim.dim_security s
    on h.security_key=s.security_key
left join dim.dim_business_line b
    on h.biz_line_key=b.biz_line_key
where
    h.asof_date between '2023-01-01' and '{p_report_date}'
    and a.default_ae_code='W300'
group by h.asof_date,s.exchange_code,s.security_code
order by h.asof_date desc,s.exchange_code,s.security_code"""

    row_num = 2
    for (
        asof_date,
        currency_code,
        fund,
        bond,
        note,
        balance,
        asset,
    ) in ads_hook.get_records(
        asset_summary_sql.format(p_report_date=p_report_date.strftime(date_fmt))
    ):
        asset_summary_worksheet[f"A{row_num}"].value = asof_date
        asset_summary_worksheet[f"B{row_num}"].value = currency_code
        asset_summary_worksheet[f"C{row_num}"].value = _to_float(fund)
        asset_summary_worksheet[f"D{row_num}"].value = _to_float(bond)
        asset_summary_worksheet[f"E{row_num}"].value = _to_float(note)
        asset_summary_worksheet[f"F{row_num}"].value = _to_float(balance)
        asset_summary_worksheet[f"G{row_num}"].value = _to_float(asset)
        row_num += 1

    row_num = 2
    for (
        asof_date,
        exchange_code,
        security_code,
        security_name,
        security_type,
        currency_code,
        market_value,
    ) in ads_hook.get_records(
        asset_product_sql.format(p_report_date=p_report_date.strftime(date_fmt))
    ):
        asset_product_worksheet[f"A{row_num}"].value = asof_date
        asset_product_worksheet[f"B{row_num}"].value = exchange_code
        asset_product_worksheet[f"C{row_num}"].value = security_code
        asset_product_worksheet[f"D{row_num}"].value = security_name
        asset_product_worksheet[f"E{row_num}"].value = security_type
        asset_product_worksheet[f"F{row_num}"].value = currency_code
        asset_product_worksheet[f"G{row_num}"].value = _to_float(market_value)
        row_num += 1

    asset_workbook.save(asset_file_path)

    trade_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/payoneer_trade_template.xlsx",
    )
    trade_workbook = openpyxl.load_workbook(trade_template)
    trade_worksheet = trade_workbook["Data"]
    trade_sql = """select
    t.trade_date,t.currency_code,
    sum(case when t.biz_line_key like 'WEALTH|FUND%' then t.buy_gross_amount else 0 end) as fund_buy,
    sum(case when t.biz_line_key like 'WEALTH|FUND%' then t.sell_gross_amount else 0 end) as fund_sell,
    sum(case when t.biz_line_key like 'WEALTH|OTCB%' then t.buy_gross_amount else 0 end) as bond_buy,
    sum(case when t.biz_line_key like 'WEALTH|OTCB%' then t.sell_gross_amount else 0 end) as bond_sell,
    sum(case when t.biz_line_key like 'WEALTH|STPD%' then t.buy_gross_amount else 0 end) as note_buy
from dws.dws_account_trade_daily_by_biz_currency t
inner join dim.dim_account p
    on t.account_no=p.account_no
where
    t.trade_date between '2023-01-01' and '{p_report_date}'
    and p.default_ae_code='W300'
group by t.trade_date,t.currency_code
order by t.trade_date desc,t.currency_code"""

    row_num = 2
    for (
        trade_date,
        currency_code,
        fund_buy,
        fund_sell,
        bond_buy,
        bond_sell,
        note_buy,
    ) in ads_hook.get_records(
        trade_sql.format(p_report_date=p_report_date.strftime(date_fmt))
    ):
        trade_worksheet[f"A{row_num}"].value = trade_date
        trade_worksheet[f"B{row_num}"].value = currency_code
        trade_worksheet[f"C{row_num}"].value = _to_float(fund_buy)
        trade_worksheet[f"D{row_num}"].value = _to_float(fund_sell)
        trade_worksheet[f"E{row_num}"].value = _to_float(bond_buy)
        trade_worksheet[f"F{row_num}"].value = _to_float(bond_sell)
        trade_worksheet[f"G{row_num}"].value = _to_float(note_buy)
        row_num += 1

    trade_workbook.save(trade_file_path)

    movement_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/payoneer_movement_template.xlsx",
    )
    movement_workbook = openpyxl.load_workbook(movement_template)
    movement_worksheet = movement_workbook["Data"]
    movement_sql = """with
tmp_payonner_account as (
    select
        a.account_no as account_no,
        max(case when m.way_desc='派安盈入金' then 1 else 0 end) as has_payonner,
        max(case when m.way_desc<>'派安盈入金' and m.way<>-1 then 1 else 0 end) as has_other,
        max(case when m.way=-1 then 1 else 0 end) as has_unknown,
        case
            when has_other=1 then 1
            when has_payonner=0 and has_other=0 and has_unknown=1 then 1
            else 0
        end as has_bank
    from dim.dim_account a
    left join (
        select *
        from dwd.dwd_cash_movement
        where
            movement_type='D'
            and is_by_client=1
    ) m
        on a.account_no=m.account_no
    where
        a.default_ae_code='W300'
    group by a.account_no
)
select
    m.trade_date,m.currency_code,
    sum(case when m.movement_type='D' then m.amount else 0 end) as cash_deposit,
    sum(case when m.movement_type='D' and (m.way_desc='派安盈入金' or (p.has_payonner=1 and p.has_bank=0)) then m.amount else 0 end) as cash_deposit_payonner,
    sum(case when m.movement_type='D' and not (m.way_desc='派安盈入金' or (p.has_payonner=1 and p.has_bank=0)) then m.amount else 0 end) as cash_deposit_bank,
    sum(case when m.movement_type='W' then m.amount else 0 end) as cash_withdraw
from dwd.dwd_cash_movement m
inner join tmp_payonner_account p
    on m.account_no=p.account_no
where
    m.is_by_client=1
    and m.trade_date between '2023-01-01' and '{p_report_date}'
group by m.trade_date,m.currency_code
order by m.trade_date desc,m.currency_code"""

    row_num = 2
    for (
        trade_date,
        currency_code,
        cash_deposit,
        _cash_deposit_payonner,
        _cash_deposit_bank,
        cash_withdraw,
    ) in ads_hook.get_records(
        movement_sql.format(p_report_date=p_report_date.strftime(date_fmt))
    ):
        movement_worksheet[f"A{row_num}"].value = trade_date
        movement_worksheet[f"B{row_num}"].value = currency_code
        movement_worksheet[f"C{row_num}"].value = _to_float(cash_deposit)
        movement_worksheet[f"D{row_num}"].value = _to_float(cash_withdraw)
        row_num += 1

    movement_workbook.save(movement_file_path)


def generate_converted_performance_report(
    p_begin_date: date, p_end_date: date, result_file_path: str
):
    """生成折标业绩结果Excel文件"""

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")
    ach_hook = MySqlHook(mysql_conn_id="achievement")

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/converted_performance_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)

    security_worksheet = workbook["股票&债券&国配&跟投&外部票据"]
    security_row_num = 2

    margin_worksheet = workbook["孖展"]
    margin_row_num = 2

    sql_achievement = get_file_content(
        "sql/ads/wealth_report/converted_performance_src_achievement.sql"
    )
    sql_commission_dw = get_file_content(
        "sql/ads/wealth_report/converted_performance_src_commission_dw.sql"
    )
    sql_commission_ach = get_file_content(
        "sql/ads/wealth_report/converted_performance_src_commission_ach.sql"
    )

    trade_type_map = {"B": "Buy", "S": "Sell"}

    # 1. 中台-数据中心-财富业绩
    for (
        _id,
        tradeWeek,
        inputDate,
        refNo,
        tradeDate,
        orderSource,
        clientTypes,
        subAcctId,
        aeCode,
        clientName,
        subscribeFlag,
        subscribeChildName,
        tradeType,
        subscribeName,
        currency,
        amount,
        amountHk,
        companyRevenueRate,
        companyRevenueUs,
        companyRevenueHk,
        salesRevenueRate,
        salesRevenueUs,
        salesRevenueHk,
        updateTime,
        operateUser,
        channelFlag,
        subscribeFlagName,
        relationType,
        relationRevenue,
        commissionInfo,
        insuranceIsInfo,
        hkFxRate,
        usFxRate,
        isPrivate,
        isFosunEco,
        orderStatus,
        lockDay,
        endDate,
        openDate,
        insuranceRate,
        isIsCommission,
        orderFlag,
    ) in ach_hook.get_records(
        sql_achievement.format(
            p_begin_date=p_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
        )
    ):
        if not (
            subscribeFlag in ("BOND", "INTERNAL")
            or (subscribeFlag == "BILL" and subscribeChildName == "外部票据")
        ):
            continue

        if not relationRevenue:
            continue

        staff_commission = []
        try:
            relationRevenueObj = json.loads(relationRevenue)
            commissionInfoObj = json.loads(commissionInfo)
            for role, revenue_info in relationRevenueObj.items():
                staff_name = revenue_info.get("user_name", None)
                if not staff_name:
                    continue

                department_name = revenue_info.get("depart_name", None)

                commission_info = commissionInfoObj.get(role, None)
                if commission_info:
                    commission_rate = commission_info.get("commission_rate", 0.0)
                    commission_hkd = commission_info.get("commission_hkd", 0.0)
                else:
                    commission_rate = 0.0
                    commission_hkd = 0.0

                staff_commission.append(
                    (staff_name, department_name, commission_rate, commission_hkd)
                )
        except json.decoder.JSONDecodeError as e:
            print(e)
            continue

        tradeType = trade_type_map.get(tradeType, tradeType)

        for (
            staff_name,
            department_name,
            commission_rate,
            commission_hkd,
        ) in staff_commission:
            security_worksheet[f"A{security_row_num}"].value = tradeWeek
            security_worksheet[f"B{security_row_num}"].value = _to_date(inputDate)
            security_worksheet[f"C{security_row_num}"].value = staff_name
            security_worksheet[f"D{security_row_num}"].value = subAcctId
            security_worksheet[f"E{security_row_num}"].value = aeCode
            security_worksheet[f"F{security_row_num}"].value = clientName
            # security_worksheet[f'G{security_row_num}'].value=xxx
            security_worksheet[f"H{security_row_num}"].value = tradeType
            security_worksheet[f"I{security_row_num}"].value = subscribeFlagName
            security_worksheet[f"J{security_row_num}"].value = subscribeName
            security_worksheet[f"K{security_row_num}"].value = currency
            security_worksheet[f"L{security_row_num}"].value = _to_float(amount)
            security_worksheet[f"M{security_row_num}"].value = _to_float(amountHk)
            security_worksheet[f"N{security_row_num}"].value = _to_float(
                salesRevenueRate
            )
            security_worksheet[f"O{security_row_num}"].value = _to_float(salesRevenueHk)
            # security_worksheet[f'P{security_row_num}'].value = xxx
            security_worksheet[f"Q{security_row_num}"].value = _to_float(
                companyRevenueRate
            )
            security_worksheet[f"R{security_row_num}"].value = _to_float(
                companyRevenueHk
            )
            security_worksheet[f"S{security_row_num}"].value = _to_float(
                commission_rate
            )
            security_worksheet[f"T{security_row_num}"].value = _to_float(commission_hkd)
            # security_worksheet[f'U{security_row_num}'].value = xxx
            # security_worksheet[f'V{security_row_num}'].value = xxx
            # security_worksheet[f'W{security_row_num}'].value = xxx
            # security_worksheet[f'X{security_row_num}'].value = xxx
            # security_worksheet[f'Y{security_row_num}'].value = xxx
            security_worksheet[f"Z{security_row_num}"].value = (
                _to_float(salesRevenueHk) - _to_float(commission_hkd)
            ) * 100.0
            security_worksheet[f"AA{security_row_num}"].value = department_name
            security_worksheet[f"AB{security_row_num}"].value = _to_float(
                companyRevenueHk
            )

            security_row_num += 1

    # 2. 中台-数据中心-汇总业绩-服务人员佣金统计 - DW部分
    for (
        trade_week,
        trade_date,
        account_no,
        ae_code,
        account_name,
        trade_type,
        subscribe_flag,
        security_name,
        staff_name,
        currency_code,
        amount,
        amount_hkd,
        company_revenue_hkd,
        sales_revenue_hkd,
        sales_revenue_rate,
        customer_rate,
        bd_rate,
        rm_rate,
        online_rate,
        offline_rate,
        manager_rate,
        consultant_rate,
        sales_commission_rate,
        sales_commission_hkd,
        department_name,
        company_revenue_hkd_raw,
        quantity,
    ) in ads_hook.get_records(
        sql_commission_dw.format(
            p_begin_date=p_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
        )
    ):
        trade_type = trade_type_map.get(trade_type, trade_type)

        if subscribe_flag in ("STOCK",'US-OPTION'):
            security_worksheet[f"A{security_row_num}"].value = trade_week
            security_worksheet[f"B{security_row_num}"].value = _to_date(trade_date)
            security_worksheet[f"C{security_row_num}"].value = staff_name
            security_worksheet[f"D{security_row_num}"].value = account_no
            security_worksheet[f"E{security_row_num}"].value = ae_code
            security_worksheet[f"F{security_row_num}"].value = account_name
            # security_worksheet[f'G{security_row_num}'].value=xxx
            security_worksheet[f"H{security_row_num}"].value = trade_type
            security_worksheet[f"I{security_row_num}"].value = "股票" if subscribe_flag == "STOCK" else "期权"
            security_worksheet[f"J{security_row_num}"].value = security_name
            security_worksheet[f"K{security_row_num}"].value = currency_code
            security_worksheet[f"L{security_row_num}"].value = _to_float(amount)
            security_worksheet[f"M{security_row_num}"].value = _to_float(amount_hkd)
            security_worksheet[f"N{security_row_num}"].value = _to_float(
                sales_revenue_rate
            )
            security_worksheet[f"O{security_row_num}"].value = _to_float(
                sales_revenue_hkd
            )
            # security_worksheet[f'P{security_row_num}'].value = xxx
            security_worksheet[f"Q{security_row_num}"].value = 1.0
            security_worksheet[f"R{security_row_num}"].value = _to_float(
                company_revenue_hkd
            )
            security_worksheet[f"S{security_row_num}"].value = _to_float(
                sales_commission_rate
            )
            security_worksheet[f"T{security_row_num}"].value = _to_float(
                sales_commission_hkd
            )
            # security_worksheet[f'U{security_row_num}'].value = xxx
            # security_worksheet[f'V{security_row_num}'].value = xxx
            # security_worksheet[f'W{security_row_num}'].value = xxx
            # security_worksheet[f'X{security_row_num}'].value = xxx
            # security_worksheet[f'Y{security_row_num}'].value = xxx
            security_worksheet[f"Z{security_row_num}"].value = (
                _to_float(sales_revenue_hkd) - _to_float(sales_commission_hkd)
            ) * 100.0
            security_worksheet[f"AA{security_row_num}"].value = department_name
            security_worksheet[f"AB{security_row_num}"].value = _to_float(
                company_revenue_hkd_raw
            )
            security_worksheet[f"AC{security_row_num}"].value = _to_float(
                quantity
            )
            security_row_num += 1
        elif subscribe_flag == "INTEREST":
            margin_worksheet[f"A{margin_row_num}"].value = trade_week
            margin_worksheet[f"B{margin_row_num}"].value = _to_date(trade_date)
            margin_worksheet[f"C{margin_row_num}"].value = staff_name
            margin_worksheet[f"D{margin_row_num}"].value = account_no
            margin_worksheet[f"E{margin_row_num}"].value = ae_code
            # margin_worksheet[f'F{margin_row_num}'].value=xxx
            margin_worksheet[f"G{margin_row_num}"].value = "孖展"
            margin_worksheet[f"H{margin_row_num}"].value = security_name
            margin_worksheet[f"I{margin_row_num}"].value = currency_code
            margin_worksheet[f"J{margin_row_num}"].value = _to_float(amount)
            margin_worksheet[f"K{margin_row_num}"].value = _to_float(amount_hkd)
            margin_worksheet[f"L{margin_row_num}"].value = _to_float(
                company_revenue_hkd
            )
            margin_worksheet[f"M{margin_row_num}"].value = _to_float(sales_revenue_rate)
            margin_worksheet[f"N{margin_row_num}"].value = _to_float(sales_revenue_hkd)
            # margin_worksheet[f'O{margin_row_num}'].value=xxx
            margin_worksheet[f"P{margin_row_num}"].value = 1.0
            margin_worksheet[f"Q{margin_row_num}"].value = _to_float(
                company_revenue_hkd
            )
            margin_worksheet[f"R{margin_row_num}"].value = _to_float(
                sales_commission_rate
            )
            margin_worksheet[f"S{margin_row_num}"].value = _to_float(
                sales_commission_hkd
            )
            # margin_worksheet[f'T{margin_row_num}'].value=xxx
            # margin_worksheet[f'U{margin_row_num}'].value=xxx
            # margin_worksheet[f'V{margin_row_num}'].value=xxx
            # margin_worksheet[f'W{margin_row_num}'].value=xxx
            # margin_worksheet[f'X{margin_row_num}'].value=xxx
            margin_worksheet[f"Y{margin_row_num}"].value = (
                _to_float(sales_revenue_hkd) - _to_float(sales_commission_hkd)
            ) * 100.0
            margin_worksheet[f"Z{margin_row_num}"].value = department_name
            margin_worksheet[f"AA{margin_row_num}"].value = _to_float(
                company_revenue_hkd_raw
            )

            margin_row_num += 1

    # 3. 中台-数据中心-汇总业绩-服务人员佣金统计 - 业绩后台部分
    for (
        trade_week,
        trade_date,
        account_no,
        ae_code,
        account_name,
        trade_type,
        subscribe_flag,
        security_name,
        staff_name,
        currency_code,
        amount,
        amount_hkd,
        company_revenue_hkd,
        sales_revenue_hkd,
        sales_commission_rate,
        sales_commission_hkd,
        department_name,
    ) in ach_hook.get_records(
        sql_commission_ach.format(
            p_begin_date=p_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
        )
    ):
        trade_type = trade_type_map.get(trade_type, trade_type)

        if subscribe_flag == "STOCK":
            security_worksheet[f"A{security_row_num}"].value = trade_week
            security_worksheet[f"B{security_row_num}"].value = _to_date(trade_date)
            security_worksheet[f"C{security_row_num}"].value = staff_name
            security_worksheet[f"D{security_row_num}"].value = account_no
            security_worksheet[f"E{security_row_num}"].value = ae_code
            security_worksheet[f"F{security_row_num}"].value = account_name
            # security_worksheet[f'G{security_row_num}'].value=xxx
            security_worksheet[f"H{security_row_num}"].value = trade_type
            security_worksheet[f"I{security_row_num}"].value = "股票"
            security_worksheet[f"J{security_row_num}"].value = security_name
            security_worksheet[f"K{security_row_num}"].value = currency_code
            security_worksheet[f"L{security_row_num}"].value = _to_float(amount)
            security_worksheet[f"M{security_row_num}"].value = _to_float(amount_hkd)
            security_worksheet[f"N{security_row_num}"].value = 1.0
            security_worksheet[f"O{security_row_num}"].value = _to_float(
                sales_revenue_hkd
            )
            # security_worksheet[f'P{security_row_num}'].value = xxx
            security_worksheet[f"Q{security_row_num}"].value = 1.0
            security_worksheet[f"R{security_row_num}"].value = _to_float(
                company_revenue_hkd
            )
            security_worksheet[f"S{security_row_num}"].value = _to_float(
                sales_commission_rate
            )
            security_worksheet[f"T{security_row_num}"].value = _to_float(
                sales_commission_hkd
            )
            # security_worksheet[f'U{security_row_num}'].value = xxx
            # security_worksheet[f'V{security_row_num}'].value = xxx
            # security_worksheet[f'W{security_row_num}'].value = xxx
            # security_worksheet[f'X{security_row_num}'].value = xxx
            # security_worksheet[f'Y{security_row_num}'].value = xxx
            security_worksheet[f"Z{security_row_num}"].value = (
                _to_float(sales_revenue_hkd) - _to_float(sales_commission_hkd)
            ) * 100.0
            security_worksheet[f"AA{security_row_num}"].value = department_name
            security_worksheet[f"AB{security_row_num}"].value = _to_float(
                company_revenue_hkd
            )

            security_row_num += 1
        elif subscribe_flag == "INTEREST":
            margin_worksheet[f"A{margin_row_num}"].value = trade_week
            margin_worksheet[f"B{margin_row_num}"].value = _to_date(trade_date)
            margin_worksheet[f"C{margin_row_num}"].value = staff_name
            margin_worksheet[f"D{margin_row_num}"].value = account_no
            margin_worksheet[f"E{margin_row_num}"].value = ae_code
            # margin_worksheet[f'F{margin_row_num}'].value=xxx
            margin_worksheet[f"G{margin_row_num}"].value = "孖展"
            margin_worksheet[f"H{margin_row_num}"].value = security_name
            margin_worksheet[f"I{margin_row_num}"].value = currency_code
            margin_worksheet[f"J{margin_row_num}"].value = _to_float(amount)
            margin_worksheet[f"K{margin_row_num}"].value = _to_float(amount_hkd)
            margin_worksheet[f"L{margin_row_num}"].value = _to_float(
                company_revenue_hkd
            )
            margin_worksheet[f"M{margin_row_num}"].value = 1.0
            margin_worksheet[f"N{margin_row_num}"].value = _to_float(sales_revenue_hkd)
            # margin_worksheet[f'O{margin_row_num}'].value=xxx
            margin_worksheet[f"P{margin_row_num}"].value = 1.0
            margin_worksheet[f"Q{margin_row_num}"].value = _to_float(
                company_revenue_hkd
            )
            margin_worksheet[f"R{margin_row_num}"].value = _to_float(
                sales_commission_rate
            )
            margin_worksheet[f"S{margin_row_num}"].value = _to_float(
                sales_commission_hkd
            )
            # margin_worksheet[f'T{margin_row_num}'].value=xxx
            # margin_worksheet[f'U{margin_row_num}'].value=xxx
            # margin_worksheet[f'V{margin_row_num}'].value=xxx
            # margin_worksheet[f'W{margin_row_num}'].value=xxx
            # margin_worksheet[f'X{margin_row_num}'].value=xxx
            margin_worksheet[f"Y{margin_row_num}"].value = (
                _to_float(sales_revenue_hkd) - _to_float(sales_commission_hkd)
            ) * 100.0
            margin_worksheet[f"Z{margin_row_num}"].value = department_name
            margin_worksheet[f"AA{margin_row_num}"].value = _to_float(
                company_revenue_hkd
            )

            margin_row_num += 1

    workbook.save(result_file_path)
    # 保存margin_worksheet到ClickHouse



def generate_atlantis_activity_report(rpt_date: date, result_file_path: str) -> bool:
    """亚特兰蒂斯活动Excel文件"""

    date_fmt = "%Y-%m-%d"

    activity_hook = MySqlHook(mysql_conn_id="activitydb")

    has_table = activity_hook.get_first("""select count(*) as n
from information_schema.tables
where
    table_schema=database()
    and table_name in ('t_atlantis_user','t_atlantis_survey')""")[0]
    has_table = has_table == 2

    if not has_table:
        print("t_atlantis_user或/和t_atlantis_survey不存在")
        return False

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/operation_explore/atlantis_activity_report_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    vip_interest_map = {
        "1": "子女海外教育规划（初中/高中/大学）",
        "2": "子女海外工作实习机会",
        "3": "海外养老退休",
        "4": "全球顶尖医疗资源保障",
        "5": "海外高端旅游服务",
        "6": "资产全球化配置",
    }
    migration_map = {
        "1": "高才签证（全球排名前100院校毕业/年薪大于250万港币）",
        "2": "优才签证（香港政府稀缺人才引进，采用打分制获批）",
        "3": "香港投资移民（3000万港币投资政府认可的相关资产7年）",
        "4": "以上都不感兴趣",
    }
    oversea_insurance_map = {
        "1": "美/澳/加/新西兰",
        "2": "葡萄牙、希腊等欧盟国家",
        "3": "东南亚地区",
        "4": "日本",
        "5": "新加坡/香港",
        "6": "暂无考虑",
    }
    hk_insurance_need_map = {
        "1": "子女教育基金",
        "2": "养老退休保障",
        "3": "资产传承（保值）",
        "4": "多元化分散配置（增值）",
        "5": "海外医疗保障",
        "6": "其他",
    }

    sql_query = """select
    s.create_time, -- 提交时间
    case
        when s.name<>'' then s.name
        else '--'
    end as name, -- 客户姓名
    case
        when s.phone<>'' and s.phone_code<>'' then concat(s.phone_code,'-',s.phone)
        when s.phone<>'' then s.phone
        when u.phone<>'' and u.phone_code<>'' then concat(u.phone_code,'-',u.phone)
        when u.phone<>'' then u.phone
        else '--'
    end as phone, -- 客户手机号
    case
        when u.aecode<>'' then u.aecode
        else '--'
    end as ae_code, -- 客户AECODE
    case u.reward
        when 1 then 'C秀普通席门票'
        when 2 then '复星财富公仔'
        else '未抽奖'
    end as reward, -- 奖品
    u.draw_time, -- 抽奖时间
    case u.receive
        when 1 then '已领取'
        else '未领取'
    end as receive, -- 是否领取
    u.receive_time, -- 领取时间
    case
        when s.address<>'' then s.address
        else '--'
    end as address, -- 常住城市
    case s.age
        when 1 then '30岁及以下'
        when 2 then '31-40岁'
        when 3 then '41-50岁'
        when 4 then '51-60岁'
        when 5 then '60岁以上'
        else '--'
    end as age, -- 年龄
    case s.career
        when 1 then '企业主或股东'
        when 2 then '公司高管'
        when 3 then '专业投资人士'
        when 4 then '专业人才，如律师、医生等'
        when 5 then '退休人士、全职太太、自由职业者'
        when 6 then '其他'
        else '--'
    end as career, -- 职业
    case s.vip_service
        when 1 then'愿意'
        when 2 then'不愿意'
        when 3 then'需要进一步了解'
        else '--'
    end as vip_service, -- 是否愿意接受“高端客户服务”权益推送
    s.vip_intersts, -- 对哪些领域感兴趣
    case s.child_education
        when 1 then '考虑过，需要进一步了解'
        when 2 then '考虑过，正在海外读书'
        when 3 then '没考虑过，暂时没有计划'
        when 4 then '没考虑过，暂时没有需求'
        else '--'
    end as child_education, -- 是否考虑过子女海外留学
    case s.child_work
        when 1 then '会提前规划'
        when 2 then '暂时不会考虑'
        when 3 then '暂时没有需求'
        else '--'
    end as child_work, -- 是否会为子女提前规划长期海外居留工作签证
    s.migrations, -- 对那种方式获取香港身份更感兴趣
    s.oversea_insurance, -- 更愿意接受以下哪些地区的海外高端医疗和养老资讯
    case s.hk_insurance
        when 1 then '未曾配置过，愿意进一步了解'
        when 2 then '已经配置过，愿意进一步了解'
        when 3 then '已经配置过，暂无了解意向'
        when 4 then '未曾配置过，暂无了解意向'
        else '--'
    end as hk_insurance, -- 是否愿意接收香港保险的相关资讯
    s.hk_insurance_need -- 考虑香港保险的规划需求
from t_atlantis_survey s
left join t_atlantis_user u
    on s.uin=u.uin
where
    s.create_time<'{p_end_date}'
order by s.create_time desc"""

    p_end_date = rpt_date + timedelta(days=1)

    row_num = 2
    for (
        create_time,
        name,
        phone,
        ae_code,
        reward,
        draw_time,
        receive,
        receive_time,
        address,
        age,
        career,
        vip_service,
        vip_interests,
        child_education,
        child_work,
        migrations,
        oversea_insurance,
        hk_insurance,
        hk_insurance_need,
    ) in activity_hook.get_records(
        sql_query.format(p_end_date=p_end_date.strftime(date_fmt))
    ):
        vip_interests = _translate_multi_val(vip_interests, vip_interest_map)
        migrations = _translate_multi_val(migrations, migration_map)
        oversea_insurance = _translate_multi_val(
            oversea_insurance, oversea_insurance_map
        )
        hk_insurance_need = _translate_multi_val(
            hk_insurance_need, hk_insurance_need_map
        )

        create_time = _format_datetime(create_time)
        draw_time = _format_datetime(draw_time)
        receive_time = _format_datetime(receive_time)

        worksheet[f"A{row_num}"].value = create_time
        worksheet[f"B{row_num}"].value = name
        worksheet[f"C{row_num}"].value = phone
        worksheet[f"D{row_num}"].value = ae_code
        worksheet[f"E{row_num}"].value = reward
        worksheet[f"F{row_num}"].value = draw_time
        worksheet[f"G{row_num}"].value = receive
        worksheet[f"H{row_num}"].value = receive_time
        worksheet[f"I{row_num}"].value = address
        worksheet[f"J{row_num}"].value = age
        worksheet[f"K{row_num}"].value = career
        worksheet[f"L{row_num}"].value = vip_service
        worksheet[f"M{row_num}"].value = vip_interests
        worksheet[f"N{row_num}"].value = child_education
        worksheet[f"O{row_num}"].value = child_work
        worksheet[f"P{row_num}"].value = migrations
        worksheet[f"Q{row_num}"].value = oversea_insurance
        worksheet[f"R{row_num}"].value = hk_insurance
        worksheet[f"S{row_num}"].value = hk_insurance_need
        row_num += 1

    workbook.save(result_file_path)
    return True


def _translate_multi_val(vals: str | None, translation_map: dict[str, str]) -> str:
    if not vals:
        return "--"

    vals = vals.split(",")
    vals = [val.strip() for val in vals]
    vals = [translation_map.get(val, val) for val in vals]

    return "; ".join(vals)


def _format_datetime(val: datetime | None) -> str:
    if not val:
        return "--"

    return val.strftime("%Y-%m-%d %H:%M:%S")


def generate_fund_daily_aum_revenue(
    p_begin_date: date, p_end_date: date, p_fund_type: int, result_file_path: str
):
    """生成货币基金/虚拟资产ETF AUM及创收明细Excel文件"""

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/channel_settle/fund_daily_aum_revenue_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    sql_query = get_file_content("sql/ads/channel_settle/fund_daily_aum_revenue.sql")

    row_num = 2
    for (
        trade_date,
        currency_code,
        exchange_code,
        security_code,
        platform,
        custodian,
        manager_cn,
        fund_manager,
        name_english,
        name_chinese,
        quantity,
        price,
        market_value,
        market_value_hkd,
        revenue_hkd,
    ) in ads_hook.get_records(
        sql_query.format(
            p_begin_date=p_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
            p_fund_type=p_fund_type,
        )
    ):
        worksheet[f"A{row_num}"].value = trade_date
        worksheet[f"B{row_num}"].value = currency_code
        worksheet[f"C{row_num}"].value = exchange_code
        worksheet[f"D{row_num}"].value = security_code
        worksheet[f"E{row_num}"].value = platform
        worksheet[f"F{row_num}"].value = custodian
        worksheet[f"G{row_num}"].value = manager_cn
        worksheet[f"H{row_num}"].value = fund_manager
        worksheet[f"I{row_num}"].value = name_english
        worksheet[f"J{row_num}"].value = name_chinese
        worksheet[f"K{row_num}"].value = _to_float(quantity)
        worksheet[f"L{row_num}"].value = _to_float(price)
        worksheet[f"M{row_num}"].value = _to_float(market_value)
        worksheet[f"N{row_num}"].value = _to_float(market_value_hkd)
        worksheet[f"O{row_num}"].value = _to_float(revenue_hkd)
        row_num += 1

    workbook.save(result_file_path)


def generate_risk_manage_monthly_interest_calculation(
    p_begin_date: date, p_end_date: date, result_file_path: str
):
    """生成风控月度利息计算Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/risk_manage/risk_manage_monthly_interest_calculation_template_hs.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Interest"]

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")
    sql_interest='''
    select  account_no,
        client_code,
        client_name,
        client_type,
        ae_code,
        ccy,
        available_balance,
        market_value,
        margin_market_value,
        interest_rate_pct,
        margin_covered_rate_pct,
        market_value_covered_rate_pct,
        market_value_uncovered_rate_pct,
        init_date,
        interest,
        fine_interest,
        posted_cr,
        posted_dr,
        margin_call from ads.ads_revenue_risk_manage_monthly_interest_m
        where init_date >=%s
        and init_date <=%s
        order by ccy, client_code, init_date
    '''
    interest_records=ads_hook.get_records(sql_interest, (p_begin_date.strftime('%Y%m%d'), p_end_date.strftime('%Y%m%d')))
    row_num = 2
    for (
        account_no,
        client_code,
        client_name,
        client_type,
        ae_code,
        ccy,
        available_balance,
        market_value,
        margin_market_value,
        interest_rate_pct,
        margin_covered_rate_pct,
        market_value_covered_rate_pct,
        market_value_uncovered_rate_pct,
        init_date,
        interest,
        fine_interest,
        posted_cr,
        posted_dr,
        margin_call,
    ) in interest_records:
        worksheet[f"A{row_num}"].value = client_code
        worksheet[f"B{row_num}"].value = client_name
        worksheet[f"C{row_num}"].value = client_type
        worksheet[f"D{row_num}"].value = ae_code
        worksheet[f"E{row_num}"].value = ccy
        worksheet[f"F{row_num}"].value = _to_float(available_balance)
        worksheet[f"G{row_num}"].value = _to_float(market_value)
        worksheet[f"H{row_num}"].value = _to_float(margin_market_value)
        worksheet[f"I{row_num}"].value = _to_float(interest_rate_pct)
        worksheet[f"J{row_num}"].value = _to_float(margin_covered_rate_pct)
        worksheet[f"K{row_num}"].value = _to_float(market_value_covered_rate_pct)
        worksheet[f"L{row_num}"].value = _to_float(market_value_uncovered_rate_pct)
        worksheet[f"M{row_num}"].value = init_date
        worksheet[f"N{row_num}"].value = _to_float(interest)
        worksheet[f"O{row_num}"].value = _to_float(fine_interest)
        worksheet[f"P{row_num}"].value = _to_float(posted_cr)
        worksheet[f"Q{row_num}"].value = _to_float(posted_dr)
        worksheet[f"R{row_num}"].value = margin_call
        row_num += 1

    workbook.save(result_file_path)


def generate_worldfirst_open_deposit_asset(p_end_date: date, result_file_path: str):
    """生成万里汇开户入金AUM统计Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/worldfirst_open_deposit_asset_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    # 1. 基金业务
    worksheet_fund = workbook["基金业务"]
    sql_query = get_file_content(
        "sql/ads/wealth_report/worldfirst_open_deposit_asset.sql"
    )

    row_num = 2
    for (
        platform_sub_type,
        stats_date,
        open_client_num,
        deposit_client_num,
        deposit_request_amount_usd,
        deposit_amount_usd,
        curr_asset_usd,
        asset_change_rate_1d,
        asset_change_rate_1w,
        asset_change_mtd,
        taikang_market_value_usd,
        taikang_buy_usd,
        taikang_sell_usd,
        hsbc_market_value_usd,
        hsbc_buy_usd,
        hsbc_sell_usd,
        efund_market_value_usd,
        efund_buy_usd,
        efund_sell_usd,
    ) in ads_hook.get_records(
        sql_query.format(p_end_date=p_end_date.strftime(date_fmt))
    ):
        worksheet_fund[f"A{row_num}"].value = platform_sub_type
        worksheet_fund[f"B{row_num}"].value = stats_date
        worksheet_fund[f"C{row_num}"].value = open_client_num
        worksheet_fund[f"D{row_num}"].value = deposit_client_num
        worksheet_fund[f"E{row_num}"].value = _to_float(deposit_request_amount_usd)
        worksheet_fund[f"F{row_num}"].value = _to_float(deposit_amount_usd)
        worksheet_fund[f"G{row_num}"].value = _to_float(asset_change_mtd)
        worksheet_fund[f"H{row_num}"].value = _to_float(curr_asset_usd)
        worksheet_fund[f"I{row_num}"].value = _to_float(asset_change_rate_1d)
        worksheet_fund[f"J{row_num}"].value = _to_float(asset_change_rate_1w)
        worksheet_fund[f"K{row_num}"].value = _to_float(taikang_market_value_usd)
        worksheet_fund[f"L{row_num}"].value = _to_float(taikang_buy_usd)
        worksheet_fund[f"M{row_num}"].value = _to_float(taikang_sell_usd)
        worksheet_fund[f"N{row_num}"].value = _to_float(hsbc_market_value_usd)
        worksheet_fund[f"O{row_num}"].value = _to_float(hsbc_buy_usd)
        worksheet_fund[f"P{row_num}"].value = _to_float(hsbc_sell_usd)
        worksheet_fund[f"Q{row_num}"].value = _to_float(efund_market_value_usd)
        worksheet_fund[f"R{row_num}"].value = _to_float(efund_buy_usd)
        worksheet_fund[f"S{row_num}"].value = _to_float(efund_sell_usd)

        row_num += 1

    # 2. 企业好易投
    worksheet_hytcm = workbook["企业好易投"]
    sql_query = get_file_content(
        "sql/ads/wealth_report/worldfirst_open_deposit_asset_hytcm.sql"
    )

    row_num = 2
    for (
        stats_date,
        open_client_num,
        deposit_client_num,
        deposit_request_amount_usd,
        deposit_amount_usd,
        curr_asset_usd,
        asset_change_rate_1d,
        asset_change_rate_1w,
        asset_change_mtd,
    ) in ads_hook.get_records(
        sql_query.format(p_end_date=p_end_date.strftime(date_fmt))
    ):
        worksheet_hytcm[f"B{row_num}"].value = stats_date
        worksheet_hytcm[f"C{row_num}"].value = open_client_num
        worksheet_hytcm[f"D{row_num}"].value = deposit_client_num
        worksheet_hytcm[f"E{row_num}"].value = _to_float(deposit_request_amount_usd)
        worksheet_hytcm[f"F{row_num}"].value = _to_float(deposit_amount_usd)
        worksheet_hytcm[f"G{row_num}"].value = _to_float(asset_change_mtd)
        worksheet_hytcm[f"H{row_num}"].value = _to_float(curr_asset_usd)
        worksheet_hytcm[f"I{row_num}"].value = _to_float(asset_change_rate_1d)
        worksheet_hytcm[f"J{row_num}"].value = _to_float(asset_change_rate_1w)

        row_num += 1

    workbook.save(result_file_path)


def generate_invest_consult_account_asset(
    p_begin_date: date, p_end_date: date, result_file_path: str
):
    """生成好易投客户每日AUM Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/invest_consult_account_asset_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Sheet1"]

    date_fmt = "%Y-%m-%d"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    sql_query = get_file_content(
        "sql/ads/wealth_report/invest_consult_account_asset.sql"
    )

    row_num = 2
    for (
        stats_date,
        account_no,
        account_name,
        ae_code,
        asset_hkd,
        consultant_name,
        invest_consult_portfolio_id,
        portfolio_name,
        portfolio_currency_code,
        management_fee,
        management_fee_hkd,
        stock_trade_amount_hkd,
        stock_commission_hkd,
        balance_usd,
        balance_hkd,
        balance_cny,
    ) in ads_hook.get_records(
        sql_query.format(
            p_begin_date=p_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
        )
    ):
        worksheet[f"A{row_num}"].value = stats_date
        worksheet[f"B{row_num}"].value = account_no
        worksheet[f"C{row_num}"].value = account_name
        worksheet[f"D{row_num}"].value = ae_code
        worksheet[f"E{row_num}"].value = _to_float(asset_hkd)
        worksheet[f"F{row_num}"].value = consultant_name
        worksheet[f"G{row_num}"].value = invest_consult_portfolio_id
        worksheet[f"H{row_num}"].value = portfolio_name
        worksheet[f"I{row_num}"].value = portfolio_currency_code
        worksheet[f"J{row_num}"].value = _to_float(management_fee)
        worksheet[f"K{row_num}"].value = _to_float(management_fee_hkd)
        worksheet[f"L{row_num}"].value = _to_float(stock_trade_amount_hkd)
        worksheet[f"M{row_num}"].value = _to_float(stock_commission_hkd)
        worksheet[f"N{row_num}"].value = _to_float(balance_usd)
        worksheet[f"O{row_num}"].value = _to_float(balance_hkd)
        worksheet[f"P{row_num}"].value = _to_float(balance_cny)

        row_num += 1

    workbook.save(result_file_path)


def generate_wealth_business_monthly_trade_revenue_cost(
    p_mtd_begin_date: date,
    p_ttm_begin_date: date,
    p_ytd_begin_date: date,
    p_end_date: date,
    result_file_path: str,
    output_private_fund_and_non_mmf: bool = False,
):
    """生成财富业务交易收入成本Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/wealth_business_monthly_trade_revenue_cost_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    date_fmt = "%Y-%m-%d"
    excel_percent_fmt = "0.00%"
    excel_number_fmt = "0.00"

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    sql_query = get_file_content(
        "sql/ads/wealth_report/wealth_business_monthly_trade_revenue_cost.sql"
    )

    ttm_aua = ads_hook.get_records(
        sql_query.format(
            p_begin_date=p_ttm_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
        )
    )
    ttm_aua = {row[0]: row[-5] for row in ttm_aua}

    ytd_aua = ads_hook.get_records(
        sql_query.format(
            p_begin_date=p_ytd_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
        )
    )
    ytd_aua = {row[0]: row[-5] for row in ytd_aua}

    row_num = 2
    for (
        biz_name,
        total_trade_amount_hkd,
        fosun_trade_amount_hkd,
        payoneer_trade_amount_hkd,
        worldfirst_trade_amount_hkd,
        w090_trade_amount_hkd,
        total_revenue_rate,
        fosun_revenue_rate,
        payoneer_revenue_rate,
        worldfirst_revenue_rate,
        w090_revenue_rate,
        finloop_revenue_rate,
        total_revenue_hkd_finloop,
        fosun_revenue_hkd_finloop,
        payoneer_revenue_hkd_finloop,
        worldfirst_revenue_hkd_finloop,
        w090_revenue_hkd_finloop,
        total_revenue_hkd,
        fosun_revenue_hkd,
        payoneer_revenue_hkd,
        worldfirst_revenue_hkd,
        w090_revenue_hkd,
        fosun_cost_hkd,
        payoneer_cost_hkd,
        worldfirst_cost_hkd,
        w090_cost_hkd,
        total_cost_hkd,
        total_revenue_hkd_no_lu,
        fosun_revenue_hkd_no_lu,
        payoneer_revenue_hkd_no_lu,
        worldfirst_revenue_hkd_no_lu,
        fosun_cost_hkd_no_lu,
        payoneer_cost_hkd_no_lu,
        worldfirst_cost_hkd_no_lu,
        total_cost_hkd_no_lu,
        total_asset_hkd,
        fosun_asset_hkd,
        payoneer_asset_hkd,
        worldfirst_asset_hkd,
        w090_asset_hkd,
        total_asset_hkd_no_lu,
        fosun_asset_hkd_no_lu,
        payoneer_asset_hkd_no_lu,
        worldfirst_asset_hkd_no_lu,
        total_aua_hkd,
        fosun_aua_hkd,
        payoneer_aua_hkd,
        worldfirst_aua_hkd,
        w090_aua_hkd,
    ) in ads_hook.get_records(
        sql_query.format(
            p_begin_date=p_mtd_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
        )
    ):
        if (not output_private_fund_and_non_mmf) and (
            biz_name in ("公募基金-非货币基金", "私募基金")
        ):
            continue

        platforms = [""]
        if biz_name in ("美国债券", "内部债券", "外部债券"):
            platforms.extend(["复星财富", "派安盈"])
        elif biz_name in ("公募基金", "公募基金-非货币基金"):
            platforms.extend(
                [
                    "复星财富",
                    "派安盈",
                    "万里汇",
                    "W090",
                    "复星财富（非Finloop）",
                    "派安盈（非Finloop）",
                    "万里汇（非Finloop）",
                ]
            )

        for platform in platforms:
            if platform == "":
                trade_amount_hkd = total_trade_amount_hkd
                revenue_rate = total_revenue_rate
                revenue_hkd_finloop = total_revenue_hkd_finloop
                revenue_hkd = total_revenue_hkd
                cost_hkd = total_cost_hkd
                asset_hkd = total_asset_hkd
                ttm_aua_hkd = ttm_aua[biz_name]
                ytd_aua_hkd = ytd_aua[biz_name]
            elif platform == "复星财富":
                trade_amount_hkd = fosun_trade_amount_hkd
                revenue_rate = fosun_revenue_rate
                revenue_hkd_finloop = fosun_revenue_hkd_finloop
                revenue_hkd = fosun_revenue_hkd
                cost_hkd = fosun_cost_hkd
                asset_hkd = fosun_asset_hkd
                ttm_aua_hkd = None
                ytd_aua_hkd = None
            elif platform == "派安盈":
                trade_amount_hkd = payoneer_trade_amount_hkd
                revenue_rate = payoneer_revenue_rate
                revenue_hkd_finloop = payoneer_revenue_hkd_finloop
                revenue_hkd = payoneer_revenue_hkd
                cost_hkd = payoneer_cost_hkd
                asset_hkd = payoneer_asset_hkd
                ttm_aua_hkd = None
                ytd_aua_hkd = None
            elif platform == "万里汇":
                trade_amount_hkd = worldfirst_trade_amount_hkd
                revenue_rate = worldfirst_revenue_rate
                revenue_hkd_finloop = worldfirst_revenue_hkd_finloop
                revenue_hkd = worldfirst_revenue_hkd
                cost_hkd = worldfirst_cost_hkd
                asset_hkd = worldfirst_asset_hkd
                ttm_aua_hkd = None
                ytd_aua_hkd = None
            elif platform == "W090":
                trade_amount_hkd = w090_trade_amount_hkd
                revenue_rate = w090_revenue_rate
                revenue_hkd_finloop = w090_revenue_hkd_finloop
                revenue_hkd = w090_revenue_hkd
                cost_hkd = w090_cost_hkd
                asset_hkd = w090_asset_hkd
                ttm_aua_hkd = None
                ytd_aua_hkd = None
            elif platform == "复星财富（非Finloop）":
                trade_amount_hkd = fosun_trade_amount_hkd
                revenue_rate = fosun_revenue_rate
                revenue_hkd_finloop = fosun_revenue_hkd_finloop
                revenue_hkd = fosun_revenue_hkd_no_lu
                cost_hkd = fosun_cost_hkd_no_lu
                asset_hkd = fosun_asset_hkd_no_lu
                ttm_aua_hkd = None
                ytd_aua_hkd = None
            elif platform == "派安盈（非Finloop）":
                trade_amount_hkd = payoneer_trade_amount_hkd
                revenue_rate = payoneer_revenue_rate
                revenue_hkd_finloop = payoneer_revenue_hkd_finloop
                revenue_hkd = payoneer_revenue_hkd_no_lu
                cost_hkd = payoneer_cost_hkd_no_lu
                asset_hkd = payoneer_asset_hkd_no_lu
                ttm_aua_hkd = None
                ytd_aua_hkd = None
            elif platform == "万里汇（非Finloop）":
                trade_amount_hkd = worldfirst_trade_amount_hkd
                revenue_rate = worldfirst_revenue_rate
                revenue_hkd_finloop = worldfirst_revenue_hkd_finloop
                revenue_hkd = worldfirst_revenue_hkd_no_lu
                cost_hkd = worldfirst_cost_hkd_no_lu
                asset_hkd = worldfirst_asset_hkd_no_lu
                ttm_aua_hkd = None
                ytd_aua_hkd = None
            else:
                raise ValueError(f"未知platform: {platform}")

            worksheet[f"A{row_num}"].value = biz_name if platform == "" else ""
            worksheet[f"B{row_num}"].value = platform
            worksheet[f"C{row_num}"].value = trade_amount_hkd
            worksheet[f"C{row_num}"].number_format = excel_number_fmt
            worksheet[f"D{row_num}"].value = revenue_rate
            worksheet[f"D{row_num}"].number_format = excel_percent_fmt
            worksheet[f"E{row_num}"].value = finloop_revenue_rate
            worksheet[f"E{row_num}"].number_format = excel_percent_fmt
            worksheet[f"F{row_num}"].value = revenue_hkd_finloop
            worksheet[f"F{row_num}"].number_format = excel_number_fmt
            worksheet[f"G{row_num}"].value = revenue_hkd
            worksheet[f"G{row_num}"].number_format = excel_number_fmt
            worksheet[f"H{row_num}"].value = cost_hkd
            worksheet[f"H{row_num}"].number_format = excel_number_fmt
            worksheet[f"J{row_num}"].value = asset_hkd
            worksheet[f"J{row_num}"].number_format = excel_number_fmt
            worksheet[f"K{row_num}"].value = ttm_aua_hkd
            worksheet[f"K{row_num}"].number_format = excel_number_fmt
            worksheet[f"L{row_num}"].value = ytd_aua_hkd
            worksheet[f"L{row_num}"].number_format = excel_number_fmt

            row_num += 1

    workbook.save(result_file_path)


def generate_wealth_sales_aum_report(
    p_rpt_date: date, result_file_path: str, only_xinghuoban: bool = False
) -> None:
    """生成财富业务AUM及销售明细AUM结果Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/wealth_sales_aum_report_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)

    date_fmt = "%Y-%m-%d"

    sql_query = get_file_content("sql/ads/wealth_report/wealth_sales_aum_report.sql")
    (
        index_staff_name,
        index_client_num,
        index_pi_num,
        index_asset_ge1e4_num,
        index_asset_total,
        index_asset_mmf,
        index_asset_ftd,
        index_asset_bond_usgov,
        index_asset_bond_internal,
        index_asset_bond_external,
        index_asset_note_fhgl,
        index_asset_note_fcn,
        index_ytd_open_asset_ge1e4hkd_num,
        index_ytd_open_asset,
    ) = range(14)

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    p_prev_date = p_rpt_date - timedelta(days=7)
    p_only_xinghuoban = 1 if only_xinghuoban else 0

    curr_result = ads_hook.get_records(
        sql_query.format(
            p_stats_date=p_rpt_date.strftime(date_fmt),
            p_only_xinghuoban=p_only_xinghuoban,
        )
    )
    prev_result = ads_hook.get_records(
        sql_query.format(
            p_stats_date=p_prev_date.strftime(date_fmt),
            p_only_xinghuoban=p_only_xinghuoban,
        )
    )

    # 1. 汇总
    worksheet_summary = workbook["私财星伙伴数据汇总"]

    curr_summary = [row for row in curr_result if row[0] == "total"][0]
    prev_summary = [row for row in prev_result if row[0] == "total"][0]

    worksheet_summary[
        "B1"
    ].value = f"{p_rpt_date.year}年{p_rpt_date.month}月{p_rpt_date.day}日"
    worksheet_summary[
        "C1"
    ].value = f"{p_prev_date.year}年{p_prev_date.month}月{p_prev_date.day}日"

    worksheet_summary["B2"].value = curr_summary[index_client_num]
    worksheet_summary["C2"].value = prev_summary[index_client_num]
    worksheet_summary["D2"].value = (
        curr_summary[index_client_num] - prev_summary[index_client_num]
    )

    worksheet_summary["B3"].value = curr_summary[index_pi_num]
    worksheet_summary["C3"].value = prev_summary[index_pi_num]
    worksheet_summary["D3"].value = (
        curr_summary[index_pi_num] - prev_summary[index_pi_num]
    )

    worksheet_summary["B4"].value = curr_summary[index_asset_ge1e4_num]
    worksheet_summary["C4"].value = prev_summary[index_asset_ge1e4_num]
    worksheet_summary["D4"].value = (
        curr_summary[index_asset_ge1e4_num] - prev_summary[index_asset_ge1e4_num]
    )

    worksheet_summary["B5"].value = curr_summary[index_ytd_open_asset_ge1e4hkd_num]
    worksheet_summary["C5"].value = prev_summary[index_ytd_open_asset_ge1e4hkd_num]
    worksheet_summary["D5"].value = (
        curr_summary[index_ytd_open_asset_ge1e4hkd_num]
        - prev_summary[index_ytd_open_asset_ge1e4hkd_num]
    )

    worksheet_summary["B6"].value = curr_summary[index_ytd_open_asset]
    worksheet_summary["C6"].value = prev_summary[index_ytd_open_asset]
    worksheet_summary["D6"].value = (
        curr_summary[index_ytd_open_asset]
        - prev_summary[index_ytd_open_asset]
    )

    worksheet_summary["B7"].value = _to_float(curr_summary[index_asset_total])
    worksheet_summary["C7"].value = _to_float(prev_summary[index_asset_total])
    worksheet_summary["D7"].value = _to_float(
        curr_summary[index_asset_total] - prev_summary[index_asset_total]
    )

    worksheet_summary["B8"].value = _to_float(curr_summary[index_asset_mmf])
    worksheet_summary["C8"].value = _to_float(prev_summary[index_asset_mmf])
    worksheet_summary["D8"].value = _to_float(
        curr_summary[index_asset_mmf] - prev_summary[index_asset_mmf]
    )

    worksheet_summary["B9"].value = _to_float(curr_summary[index_asset_ftd])
    worksheet_summary["C9"].value = _to_float(prev_summary[index_asset_ftd])
    worksheet_summary["D9"].value = _to_float(
        curr_summary[index_asset_ftd] - prev_summary[index_asset_ftd]
    )

    worksheet_summary["B10"].value = _to_float(curr_summary[index_asset_bond_usgov])
    worksheet_summary["C10"].value = _to_float(prev_summary[index_asset_bond_usgov])
    worksheet_summary["D10"].value = _to_float(
        curr_summary[index_asset_bond_usgov] - prev_summary[index_asset_bond_usgov]
    )

    worksheet_summary["B11"].value = _to_float(curr_summary[index_asset_bond_internal])
    worksheet_summary["C11"].value = _to_float(prev_summary[index_asset_bond_internal])
    worksheet_summary["D11"].value = _to_float(
        curr_summary[index_asset_bond_internal]
        - prev_summary[index_asset_bond_internal]
    )

    worksheet_summary["B12"].value = _to_float(curr_summary[index_asset_bond_external])
    worksheet_summary["C12"].value = _to_float(prev_summary[index_asset_bond_external])
    worksheet_summary["D12"].value = _to_float(
        curr_summary[index_asset_bond_external]
        - prev_summary[index_asset_bond_external]
    )

    worksheet_summary["B13"].value = _to_float(curr_summary[index_asset_note_fhgl])
    worksheet_summary["C13"].value = _to_float(prev_summary[index_asset_note_fhgl])
    worksheet_summary["D13"].value = _to_float(
        curr_summary[index_asset_note_fhgl] - prev_summary[index_asset_note_fhgl]
    )

    worksheet_summary["B14"].value = _to_float(curr_summary[index_asset_note_fcn])
    worksheet_summary["C14"].value = _to_float(prev_summary[index_asset_note_fcn])
    worksheet_summary["D14"].value = _to_float(
        curr_summary[index_asset_note_fcn] - prev_summary[index_asset_note_fcn]
    )
    # 修改workseet名称
    if only_xinghuoban is False:
        worksheet_summary.title = f"财富业务数据汇总"

    # 2. 明细
    worksheet_detail = workbook["销售明细"]

    prev_result = {row[0]: row for row in prev_result}
    empty_row = ("", *([0] * 13))

    row_num = 2
    for curr_row in curr_result:
        staff_name = curr_row[index_staff_name]
        if staff_name == "total":
            continue

        prev_row = prev_result.get(staff_name, empty_row)

        worksheet_detail[f"A{row_num}"].value = staff_name

        worksheet_detail[f"B{row_num}"].value = curr_row[index_client_num]
        worksheet_detail[f"C{row_num}"].value = (
            curr_row[index_client_num] - prev_row[index_client_num]
        )

        worksheet_detail[f"D{row_num}"].value = curr_row[index_pi_num]
        worksheet_detail[f"E{row_num}"].value = (
            curr_row[index_pi_num] - prev_row[index_pi_num]
        )

        worksheet_detail[f"F{row_num}"].value = curr_row[index_asset_ge1e4_num]
        worksheet_detail[f"G{row_num}"].value = (
            curr_row[index_asset_ge1e4_num] - prev_row[index_asset_ge1e4_num]
        )

        worksheet_detail[f"H{row_num}"].value = curr_row[
            index_ytd_open_asset_ge1e4hkd_num
        ]
        worksheet_detail[f"I{row_num}"].value = (
            curr_row[index_ytd_open_asset_ge1e4hkd_num]
            - prev_row[index_ytd_open_asset_ge1e4hkd_num]
        )

        worksheet_detail[f"J{row_num}"].value = _to_float(curr_row[index_ytd_open_asset])
        worksheet_detail[f"K{row_num}"].value = _to_float(
            curr_row[index_ytd_open_asset] - prev_row[index_ytd_open_asset]
        )

        worksheet_detail[f"L{row_num}"].value = _to_float(curr_row[index_asset_total])
        worksheet_detail[f"M{row_num}"].value = _to_float(
            curr_row[index_asset_total] - prev_row[index_asset_total]
        )

        worksheet_detail[f"N{row_num}"].value = _to_float(curr_row[index_asset_mmf])
        worksheet_detail[f"O{row_num}"].value = _to_float(
            curr_row[index_asset_mmf] - prev_row[index_asset_mmf]
        )

        worksheet_detail[f"P{row_num}"].value = _to_float(curr_row[index_asset_ftd])
        worksheet_detail[f"Q{row_num}"].value = _to_float(
            curr_row[index_asset_ftd] - prev_row[index_asset_ftd]
        )

        worksheet_detail[f"R{row_num}"].value = _to_float(
            curr_row[index_asset_bond_usgov]
        )
        worksheet_detail[f"S{row_num}"].value = _to_float(
            curr_row[index_asset_bond_usgov] - prev_row[index_asset_bond_usgov]
        )

        worksheet_detail[f"T{row_num}"].value = _to_float(
            curr_row[index_asset_bond_internal]
        )
        worksheet_detail[f"U{row_num}"].value = _to_float(
            curr_row[index_asset_bond_internal] - prev_row[index_asset_bond_internal]
        )

        worksheet_detail[f"V{row_num}"].value = _to_float(
            curr_row[index_asset_bond_external]
        )
        worksheet_detail[f"W{row_num}"].value = _to_float(
            curr_row[index_asset_bond_external] - prev_row[index_asset_bond_external]
        )

        worksheet_detail[f"X{row_num}"].value = _to_float(
            curr_row[index_asset_note_fhgl]
        )
        worksheet_detail[f"Y{row_num}"].value = _to_float(
            curr_row[index_asset_note_fhgl] - prev_row[index_asset_note_fhgl]
        )

        worksheet_detail[f"Z{row_num}"].value = _to_float(
            curr_row[index_asset_note_fcn]
        )
        worksheet_detail[f"AA{row_num}"].value = _to_float(
            curr_row[index_asset_note_fcn] - prev_row[index_asset_note_fcn]
        )

        row_num += 1

    workbook.save(result_file_path)


def generate_corp_cm_open_deposit_asset(
    p_rpt_date: date, result_file_path: str
) -> None:
    """生成现金通统计报表Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/corp_cm_open_deposit_asset_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet_summary = workbook["概览"]
    worksheet_detail = workbook["明细"]

    date_fmt = "%Y-%m-%d"

    p_cur_period_begin_date = p_rpt_date - timedelta(days=p_rpt_date.weekday())
    p_pre_period_end_date = p_cur_period_begin_date - timedelta(days=1)
    p_pre_period_begin_date = p_pre_period_end_date - timedelta(days=6)

    sql_query = get_file_content("sql/ads/wealth_report/corp_cm_open_deposit_asset.sql")

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    # summary
    (
        open_num,
        deposit_client_num,
        deposit_request_amount_usd,
        deposit_amount_usd,
        cur_market_value_usd,
        market_value_change_usd,
        cum_revenue_usd,
        cur_period_revenue_usd,
        cum_subscribe_amount_usd,
        cur_period_subscribe_amount_usd,
        cum_redeem_amount_usd,
        cur_period_redeem_amount_usd,
    ) = ads_hook.get_first(
        sql_query.format(
            p_cur_period_end_date=p_rpt_date.strftime(date_fmt),
            p_cur_period_begin_date=p_cur_period_begin_date.strftime(date_fmt),
            p_pre_period_end_date=p_pre_period_end_date.strftime(date_fmt),
            p_pre_period_begin_date=p_pre_period_begin_date.strftime(date_fmt),
            result_type="tmp_summary",
        )
    )

    worksheet_summary["B2"].value = p_rpt_date
    worksheet_summary["C2"].value = open_num
    worksheet_summary["D2"].value = deposit_client_num
    worksheet_summary["E2"].value = _to_float(deposit_request_amount_usd)
    worksheet_summary["F2"].value = _to_float(deposit_amount_usd)
    worksheet_summary["G2"].value = _to_float(cur_market_value_usd)
    worksheet_summary["H2"].value = _to_float(market_value_change_usd)
    worksheet_summary["I2"].value = _to_float(cum_revenue_usd)
    worksheet_summary["J2"].value = _to_float(cur_period_revenue_usd)
    worksheet_summary["K2"].value = _to_float(cum_subscribe_amount_usd)
    worksheet_summary["L2"].value = _to_float(cur_period_subscribe_amount_usd)
    worksheet_summary["M2"].value = _to_float(cum_redeem_amount_usd)
    worksheet_summary["N2"].value = _to_float(cur_period_redeem_amount_usd)

    # detail
    row_num = 2
    for (
        client_name,
        department_name,
        staff_name,
        open_status,
        apply_date,
        open_date,
        deposit_amount_usd,
        cum_subscribe_amount_usd,
        cur_market_value_usd,
        cum_redeem_amount_usd,
    ) in ads_hook.get_records(
        sql_query.format(
            p_cur_period_end_date=p_rpt_date.strftime(date_fmt),
            p_cur_period_begin_date=p_cur_period_begin_date.strftime(date_fmt),
            p_pre_period_end_date=p_pre_period_end_date.strftime(date_fmt),
            p_pre_period_begin_date=p_pre_period_begin_date.strftime(date_fmt),
            result_type="tmp_detail",
        )
    ):
        worksheet_detail[f"A{row_num}"].value = client_name
        worksheet_detail[f"B{row_num}"].value = department_name
        worksheet_detail[f"C{row_num}"].value = staff_name
        worksheet_detail[f"D{row_num}"].value = open_status
        worksheet_detail[f"E{row_num}"].value = apply_date
        worksheet_detail[f"F{row_num}"].value = open_date
        worksheet_detail[f"G{row_num}"].value = deposit_amount_usd
        worksheet_detail[f"H{row_num}"].value = cum_subscribe_amount_usd
        worksheet_detail[f"I{row_num}"].value = cur_market_value_usd
        worksheet_detail[f"J{row_num}"].value = cum_redeem_amount_usd
        row_num += 1

    workbook.save(result_file_path)


def generate_wealth_public_fund_subscription(
    p_begin_date: date, p_end_date: date, result_file_path: str
) -> None:
    """生成私财星伙伴所有客户公募基金认购明细Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/wealth_public_fund_subscription_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)

    date_fmt = "%Y-%m-%d"

    sql_query = get_file_content(
        "sql/ads/wealth_report/wealth_public_fund_subscription.sql"
    )

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    # 1. 私财星伙伴客户
    worksheet_wealth = workbook["私财星伙伴客户"]

    row_num = 2
    for (
        staff_name,
        department_name,
        account_name,
        account_no,
        ae_code,
        trade_date,
        isin_code,
        fund_name,
        currency_code,
        gross_amount,
        gross_amount_hkd,
        sub_red_fee_hkd,
    ) in ads_hook.get_records(
        sql_query.format(
            p_begin_date=p_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
            p_only_wealth=1,
        )
    ):
        worksheet_wealth[f"A{row_num}"].value = staff_name
        worksheet_wealth[f"B{row_num}"].value = department_name
        worksheet_wealth[f"C{row_num}"].value = account_name
        worksheet_wealth[f"D{row_num}"].value = account_no
        worksheet_wealth[f"E{row_num}"].value = ae_code
        worksheet_wealth[f"F{row_num}"].value = trade_date
        worksheet_wealth[f"G{row_num}"].value = isin_code
        worksheet_wealth[f"H{row_num}"].value = fund_name
        worksheet_wealth[f"I{row_num}"].value = currency_code
        worksheet_wealth[f"J{row_num}"].value = _to_float(gross_amount)
        worksheet_wealth[f"K{row_num}"].value = _to_float(gross_amount_hkd)
        worksheet_wealth[f"L{row_num}"].value = _to_float(sub_red_fee_hkd)
        row_num += 1

    # 2. 所有客户
    worksheet_all = workbook["所有客户"]

    row_num = 2
    for (
        staff_name,
        department_name,
        account_name,
        account_no,
        ae_code,
        trade_date,
        isin_code,
        fund_name,
        currency_code,
        gross_amount,
        gross_amount_hkd,
        sub_red_fee_hkd,
    ) in ads_hook.get_records(
        sql_query.format(
            p_begin_date=p_begin_date.strftime(date_fmt),
            p_end_date=p_end_date.strftime(date_fmt),
            p_only_wealth=0,
        )
    ):
        worksheet_all[f"A{row_num}"].value = staff_name
        worksheet_all[f"B{row_num}"].value = department_name
        worksheet_all[f"C{row_num}"].value = account_name
        worksheet_all[f"D{row_num}"].value = account_no
        worksheet_all[f"E{row_num}"].value = ae_code
        worksheet_all[f"F{row_num}"].value = trade_date
        worksheet_all[f"G{row_num}"].value = isin_code
        worksheet_all[f"H{row_num}"].value = fund_name
        worksheet_all[f"I{row_num}"].value = currency_code
        worksheet_all[f"J{row_num}"].value = _to_float(gross_amount)
        worksheet_all[f"K{row_num}"].value = _to_float(gross_amount_hkd)
        worksheet_all[f"L{row_num}"].value = _to_float(sub_red_fee_hkd)
        row_num += 1

    workbook.save(result_file_path)


def generate_virtual_asset_revenue_detail(result_file_path: str) -> None:
    """生成虚拟资产创收明细Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/virtual_asset/virtual_asset_revenue_detail_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    # 1. 绑定钱包
    worksheet_bind = workbook["钱包绑定明细"]

    sql_query = get_file_content(
        "sql/ads/virtual_asset/virtual_asset_revenue_detail_bind.sql"
    )

    row_num = 2
    for (
        account_no,
        account_name,
        ae_code,
        staff_name,
        fee_currency_code,
        bind_fee,
        va_wallet_type,
        bind_date,
        bind_status,
    ) in ads_hook.get_records(sql_query):
        worksheet_bind[f"A{row_num}"].value = account_no
        worksheet_bind[f"B{row_num}"].value = account_name
        worksheet_bind[f"C{row_num}"].value = ae_code
        worksheet_bind[f"D{row_num}"].value = staff_name
        worksheet_bind[f"E{row_num}"].value = fee_currency_code
        worksheet_bind[f"F{row_num}"].value = bind_fee
        worksheet_bind[f"G{row_num}"].value = va_wallet_type
        worksheet_bind[f"H{row_num}"].value = bind_date
        worksheet_bind[f"I{row_num}"].value = bind_status
        row_num += 1

    # 2. 实物申购
    worksheet_in_kind = workbook["InKind交易费用明细"]

    sql_query = get_file_content(
        "sql/ads/virtual_asset/virtual_asset_revenue_detail_in_kind.sql"
    )

    row_num = 2
    for (
        common_account_no,
        account_name,
        ae_code,
        staff_name,
        order_type,
        complete_date,
        order_status,
        common_security_name,
        common_security_code,
        confirm_common_quantity,
        va_security_code,
        apply_va_quantity,
        fee_currency_code,
        handling_fee,
        confirm_va_quantity,
        spread_va_quantity,
    ) in ads_hook.get_records(sql_query):
        worksheet_in_kind[f"A{row_num}"].value = common_account_no
        worksheet_in_kind[f"B{row_num}"].value = account_name
        worksheet_in_kind[f"C{row_num}"].value = ae_code
        worksheet_in_kind[f"D{row_num}"].value = staff_name
        worksheet_in_kind[f"E{row_num}"].value = order_type
        worksheet_in_kind[f"F{row_num}"].value = complete_date
        worksheet_in_kind[f"G{row_num}"].value = order_status
        worksheet_in_kind[f"H{row_num}"].value = common_security_name
        worksheet_in_kind[f"I{row_num}"].value = common_security_code
        worksheet_in_kind[f"J{row_num}"].value = confirm_common_quantity
        worksheet_in_kind[f"K{row_num}"].value = va_security_code
        worksheet_in_kind[f"L{row_num}"].value = apply_va_quantity
        worksheet_in_kind[f"M{row_num}"].value = fee_currency_code
        worksheet_in_kind[f"N{row_num}"].value = handling_fee
        worksheet_in_kind[f"O{row_num}"].value = confirm_va_quantity
        worksheet_in_kind[f"P{row_num}"].value = va_security_code
        worksheet_in_kind[f"Q{row_num}"].value = spread_va_quantity
        row_num += 1

    # 3. 稳定币兑换
    worksheet_otc = workbook["稳定币兑换交易费用明细"]

    sql_query = '''
                select account_no
                     , account_name
                     , ae_code
                     , staff_name
                     , order_type
                     , if(complete_date = '1900-01-01', '', DATE_FORMAT(complete_date, '%Y-%m-%d')) as complete_date
                     , order_status
                     , trade_type
                     , out_asset_type
                     , in_asset_type
                     , exchange_price
                     , vasp_exchange_price
                     , out_amount_client
                     , in_amount_client
                     , out_amount_confirm
                     , in_amount_confirm
                     , spread_security_code
                     , spread_amount
                     , spread_amount_hkd
                     , fee_ratio
                     , fee_ratio_source
                     , spread_amount_hkd_deduct_nominal
                     , star_chain_revenue_hkd
                     , sales_revenue_hkd
                from ads.ads_revenue_virtual_asset_revenue_detail_otc_d
                '''

    row_num = 2
    for (
        account_no,
        account_name,
        ae_code,
        staff_name,
        order_type,
        complete_date,
        order_status,
        trade_type,
        out_asset_type,
        in_asset_type,
        exchange_price,
        vasp_exchange_price,
        out_amount_client,
        in_amount_client,
        out_amount_confirm,
        in_amount_confirm,
        spread_security_code,
        spread_amount,
        spread_amount_hkd,
        fee_ratio,
        fee_ratio_source,
        spread_amount_hkd_deduct_nominal,
        star_chain_revenue_hkd,
        sales_revenue_hkd,
    ) in ads_hook.get_records(sql_query):
        worksheet_otc[f"A{row_num}"].value = account_no
        worksheet_otc[f"B{row_num}"].value = account_name
        worksheet_otc[f"C{row_num}"].value = ae_code
        worksheet_otc[f"D{row_num}"].value = staff_name
        worksheet_otc[f"E{row_num}"].value = order_type
        worksheet_otc[f"F{row_num}"].value = complete_date
        worksheet_otc[f"G{row_num}"].value = order_status
        worksheet_otc[f"H{row_num}"].value = trade_type
        worksheet_otc[f"I{row_num}"].value = out_asset_type
        worksheet_otc[f"J{row_num}"].value = in_asset_type
        worksheet_otc[f"K{row_num}"].value = exchange_price
        worksheet_otc[f"L{row_num}"].value = vasp_exchange_price
        worksheet_otc[f"M{row_num}"].value = out_amount_client
        worksheet_otc[f"N{row_num}"].value = in_amount_client
        worksheet_otc[f"O{row_num}"].value = out_amount_confirm
        worksheet_otc[f"P{row_num}"].value = in_amount_confirm
        worksheet_otc[f"Q{row_num}"].value = spread_security_code
        worksheet_otc[f"R{row_num}"].value = spread_amount
        worksheet_otc[f"S{row_num}"].value = spread_amount_hkd
        worksheet_otc[f"T{row_num}"].value = fee_ratio
        worksheet_otc[f"U{row_num}"].value = fee_ratio_source
        worksheet_otc[f"V{row_num}"].value = spread_amount_hkd_deduct_nominal
        worksheet_otc[f"W{row_num}"].value = star_chain_revenue_hkd
        worksheet_otc[f"X{row_num}"].value = sales_revenue_hkd
        row_num += 1


    workbook.save(result_file_path)


def generate_esop_business_summary(p_end_date: date, result_file_path: str) -> None:
    """生成ESOP Business Summary Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/esop/esop_business_summary_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")
    date_fmt = "%Y-%m-%d"

    # 1. Summary
    worksheet_summary = workbook["Summary"]
    sql_summary = get_file_content("sql/ads/esop/esop_business_summary_01_summary.sql")

    account_num, asset, balance, holding, revenue = ads_hook.get_first(
        sql_summary.format(p_end_date=p_end_date.strftime(date_fmt))
    )

    worksheet_summary["A2"].value = account_num
    worksheet_summary["B2"].value = holding
    worksheet_summary["C2"].value = balance
    worksheet_summary["D2"].value = asset
    worksheet_summary["E2"].value = revenue

    # 2. Account
    worksheet_account = workbook["Account"]
    sql_account = get_file_content("sql/ads/esop/esop_business_summary_02_account.sql")

    row_num = 2
    for (
        account_no,
        account_name,
        ae_code,
        company_name,
        open_date,
    ) in ads_hook.get_records(
        sql_account.format(p_end_date=p_end_date.strftime(date_fmt))
    ):
        worksheet_account[f"A{row_num}"].value = account_no
        worksheet_account[f"B{row_num}"].value = account_name
        worksheet_account[f"C{row_num}"].value = ae_code
        worksheet_account[f"D{row_num}"].value = company_name
        worksheet_account[f"E{row_num}"].value = open_date

        row_num += 1

    # 3. Assets
    worksheet_assets = workbook["Assets"]
    sql_assets = get_file_content("sql/ads/esop/esop_business_summary_03_assets.sql")

    row_num = 2
    for (
        account_no,
        account_name,
        asset_hkd,
        balance_hkd,
        holding_hkd,
        asset_usd,
        balance_usd,
        holding_usd,
        asset_cny,
        balance_cny,
        holding_cny,
    ) in ads_hook.get_records(
        sql_assets.format(p_end_date=p_end_date.strftime(date_fmt))
    ):
        worksheet_assets[f"A{row_num}"].value = account_no
        worksheet_assets[f"B{row_num}"].value = account_name
        worksheet_assets[f"C{row_num}"].value = holding_hkd
        worksheet_assets[f"D{row_num}"].value = balance_hkd
        worksheet_assets[f"E{row_num}"].value = asset_hkd
        worksheet_assets[f"F{row_num}"].value = holding_usd
        worksheet_assets[f"G{row_num}"].value = balance_usd
        worksheet_assets[f"H{row_num}"].value = asset_usd
        worksheet_assets[f"I{row_num}"].value = holding_cny
        worksheet_assets[f"J{row_num}"].value = balance_cny
        worksheet_assets[f"K{row_num}"].value = asset_cny

        row_num += 1

    # 4. PL
    worksheet_pl = workbook["PL"]
    sql_pl = get_file_content("sql/ads/esop/esop_business_summary_04_pl.sql")

    row_num = 2
    for (
        tran_type,
        tran_month,
        tran_id,
        account_no,
        account_name,
        tran_date,
        tran_amount,
        currency_code,
        revenue,
        revenue_hkd,
        tran_ref,
    ) in ads_hook.get_records(sql_pl.format(p_end_date=p_end_date.strftime(date_fmt))):
        worksheet_pl[f"A{row_num}"].value = tran_type
        worksheet_pl[f"B{row_num}"].value = tran_month
        worksheet_pl[f"C{row_num}"].value = tran_id
        worksheet_pl[f"D{row_num}"].value = account_name
        worksheet_pl[f"E{row_num}"].value = account_no
        worksheet_pl[f"F{row_num}"].value = tran_date
        worksheet_pl[f"G{row_num}"].value = tran_amount
        worksheet_pl[f"H{row_num}"].value = currency_code
        worksheet_pl[f"I{row_num}"].value = revenue
        worksheet_pl[f"J{row_num}"].value = revenue_hkd
        worksheet_pl[f"K{row_num}"].value = tran_ref

        row_num += 1

    workbook.save(result_file_path)


def generate_worldfirst_payonner_account_list(
    p_end_date: date, result_file_path: str
) -> None:
    """生成万里汇派安盈开户名单Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/compliance/worldfirst_payonner_account_list_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["查询结果"]

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")
    sql_query = get_file_content(
        "sql/ads/compliance/worldfirst_payonner_account_list.sql"
    )

    row_num = 2
    for (
        platform,
        account_no,
        name_chinese,
        name_english,
        registration_region,
        business_registration_no,
        ae_code,
        open_date,
        account_status,
    ) in ads_hook.get_records(sql_query.format(p_end_date=p_end_date.isoformat())):
        worksheet[f"A{row_num}"].value = platform
        worksheet[f"B{row_num}"].value = account_no
        worksheet[f"C{row_num}"].value = name_chinese
        worksheet[f"D{row_num}"].value = name_english
        worksheet[f"E{row_num}"].value = registration_region
        worksheet[f"F{row_num}"].value = business_registration_no
        worksheet[f"G{row_num}"].value = ae_code
        worksheet[f"H{row_num}"].value = open_date
        worksheet[f"I{row_num}"].value = account_status
        row_num += 1

    workbook.save(result_file_path)


def generate_online_operation_conversion_report(
    p_end_date: date, result_file_path: str
) -> None:
    """生成渠道用户转化情况Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/operation_explore/online_operation_conversion_report_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    template_worksheet = workbook["Sheet1"]

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")
    sql_query = get_file_content(
        "sql/ads/operation_explore/online_operation_conversion_report.sql"
    )

    tasks = [
        (
            workbook.copy_worksheet(template_worksheet),
            "当年新增用户",
            date(p_end_date.year, 1, 1),
            p_end_date,
        ),
        (
            workbook.copy_worksheet(template_worksheet),
            "当月新增用户",
            date(p_end_date.year, p_end_date.month, 1),
            p_end_date,
        ),
        (
            workbook.copy_worksheet(template_worksheet),
            "当周新增用户",
            p_end_date - timedelta(days=p_end_date.weekday()),
            p_end_date,
        ),
        (
            workbook.copy_worksheet(template_worksheet),
            "当日新增用户",
            p_end_date,
            p_end_date,
        ),
    ]

    for worksheet, worksheet_title, p_begin_date, p_end_date in tasks:
        row_num = 2
        for (
            channel,
            register_num,
            open_num,
            first_deposit_num,
            valid_deposit_num,
            trade_all_num,
            trade_us_num,
            trade_hk_num,
            trade_fund_num,
            ipo_apply_num,
            revenue,
            arpu,
            loss_num,
            settle_num,
            settle_rate,
        ) in ads_hook.get_records(
            sql_query.format(
                p_begin_date=p_begin_date.isoformat(), p_end_date=p_end_date.isoformat()
            )
        ):
            worksheet[f"A{row_num}"].value = channel
            worksheet[f"B{row_num}"].value = register_num
            worksheet[f"C{row_num}"].value = open_num
            worksheet[f"D{row_num}"].value = first_deposit_num
            worksheet[f"E{row_num}"].value = valid_deposit_num
            worksheet[f"F{row_num}"].value = trade_all_num
            worksheet[f"G{row_num}"].value = trade_hk_num
            worksheet[f"H{row_num}"].value = trade_us_num
            worksheet[f"I{row_num}"].value = trade_fund_num
            worksheet[f"J{row_num}"].value = ipo_apply_num
            worksheet[f"K{row_num}"].value = (
                round(revenue, 2) if revenue is not None else None
            )
            worksheet[f"L{row_num}"].value = (
                round(arpu, 2) if arpu is not None else None
            )
            worksheet[f"M{row_num}"].value = loss_num
            worksheet[f"N{row_num}"].value = settle_num
            worksheet[f"O{row_num}"].value = settle_rate
            row_num += 1

        worksheet.title = worksheet_title

    workbook.remove(template_worksheet)
    workbook.save(result_file_path)


def generate_invest_consult_portfolio_detail(
    p_end_date: date, result_file_path: str
) -> None:
    """生成李晓翀管理组合数据明细Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/invest_consult_portfolio_detail_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet_trade = workbook["当年交易组合交易记录"]
    worksheet_holding = workbook["客户持仓明细"]

    sql_01_common = get_splitted_sql(
        "sql/ads/wealth_report/invest_consult_portfolio_detail_01_common.sql"
    )
    sql_02_trade = get_file_content(
        "sql/ads/wealth_report/invest_consult_portfolio_detail_02_trade.sql"
    )
    sql_03_asset = get_file_content(
        "sql/ads/wealth_report/invest_consult_portfolio_detail_03_asset.sql"
    )
    sql_04_yield = get_file_content(
        "sql/ads/wealth_report/invest_consult_portfolio_detail_04_yield.sql"
    )
    sql_05_clear = get_splitted_sql(
        "sql/ads/wealth_report/invest_consult_portfolio_detail_05_clear.sql"
    )

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    ads_hook.run(
        [
            sql.format(p_end_date=p_end_date.isoformat(), p_consultant_name="李晓翀")
            for sql in sql_01_common
        ]
    )

    border_side = openpyxl.styles.Side(style="thin", color="FF000000")
    border = openpyxl.styles.Border(
        left=border_side, right=border_side, top=border_side, bottom=border_side
    )
    center = openpyxl.styles.Alignment(horizontal="center", vertical="center")
    excel_percent_fmt = "0.00%"
    excel_number_fmt = "0.00"

    # 交易记录
    row_num = 2
    ytd_begin_date = date(p_end_date.year, 1, 1)
    for (
        portfolio_id,
        portfolio_name,
        account_no,
        trade_date,
        security_code,
        security_name,
        trade_type,
        quantity,
        price,
        gross_amount_hkd,
        fx_rate_to_hkd,
    ) in ads_hook.get_records(
        sql_02_trade.format(
            p_begin_date=ytd_begin_date.isoformat(), p_end_date=p_end_date.isoformat()
        )
    ):
        worksheet_trade[f"A{row_num}"].value = portfolio_id
        worksheet_trade[f"B{row_num}"].value = portfolio_name
        worksheet_trade[f"C{row_num}"].value = account_no
        worksheet_trade[f"D{row_num}"].value = trade_date
        worksheet_trade[f"E{row_num}"].value = security_code
        worksheet_trade[f"F{row_num}"].value = security_name
        worksheet_trade[f"G{row_num}"].value = trade_type
        worksheet_trade[f"H{row_num}"].value = quantity
        worksheet_trade[f"I{row_num}"].value = price
        worksheet_trade[f"I{row_num}"].number_format = excel_number_fmt
        worksheet_trade[f"J{row_num}"].value = gross_amount_hkd
        worksheet_trade[f"J{row_num}"].number_format = excel_number_fmt
        worksheet_trade[f"K{row_num}"].value = round(fx_rate_to_hkd, 2)
        worksheet_trade[f"K{row_num}"].number_format = excel_number_fmt
        row_num += 1

    # 持仓明细
    result_statement = "select * from tmp_init_asset"
    account_init_asset = ads_hook.get_records(
        sql_03_asset.format(
            p_end_date=p_end_date.isoformat(),
            result_statement=result_statement,
        )
    )
    account_init_asset = {
        account_no: init_asset_hkd for account_no, init_asset_hkd in account_init_asset
    }

    result_statement = """select
	a.account_no as account_no,
	ifNull(ast.balance_hkd,0) as balance_hkd,
	ifnull(ast.stock_us_hkd,0) as stock_us_hkd,
	ifnull(ast.stock_hk_hkd,0) as stock_hk_hkd,
	ifnull(ast.end_asset_hkd,0) as end_asset_hkd,
	ast.balance_ratio as balance_ratio,
	ast.stock_us_ratio as stock_us_ratio,
	ast.stock_hk_ratio as stock_hk_ratio
from tmp_invest_consult_portfolio_detail_account a
left join tmp_end_asset ast
	on a.account_no=ast.account_no
order by a.account_no"""
    account_end_asset = ads_hook.get_records(
        sql_03_asset.format(
            p_end_date=p_end_date.isoformat(),
            result_statement=result_statement,
        )
    )
    account_end_asset = {row[0]: row[1:] for row in account_end_asset}

    account_yield = ads_hook.get_records(
        sql_04_yield.format(p_end_date=p_end_date.isoformat())
    )
    account_yield = {row[0]: row[1:] for row in account_yield}

    result_statement = """select
   v_asset_date as asof_date,
   portfolio_id,portfolio_name,
   a.account_no as account_no,
   security_code,security_name,quantity,market_value_hkd,market_value_ratio
from tmp_invest_consult_portfolio_detail_account a
left join tmp_holding h
    on a.account_no=h.account_no
order by a.portfolio_id,a.account_no,h.security_code"""
    account_holding = ads_hook.get_records(
        sql_03_asset.format(
            p_end_date=p_end_date.isoformat(), result_statement=result_statement
        )
    )

    ads_hook.run(sql_05_clear)

    header_cells = list(
        worksheet_holding.iter_rows(min_row=1, max_row=1, values_only=True)
    )[0]

    row_num = 2
    current_account = None
    current_account_begin_row_num = 0
    for (
        asof_date,
        portfolio_id,
        portfolio_name,
        account_no,
        security_code,
        security_name,
        quantity,
        market_value_hkd,
        market_value_ratio,
    ) in account_holding:
        if current_account is None:
            current_account = account_no
            current_account_begin_row_num = row_num
        elif current_account != account_no:
            init_asset_hkd = float(account_init_asset.get(current_account, 0))
            (
                balance_hkd,
                stock_us_hkd,
                stock_hk_hkd,
                end_asset_hkd,
                balance_ratio,
                stock_us_ratio,
                stock_hk_ratio,
            ) = account_end_asset[current_account]
            (
                _,
                _,
                acc_yield,
                acc_yield_rate,
                acc_fee,
                _,
                _,
                ytd_yield,
                ytd_yield_rate,
                ytd_fee,
                _,
                _,
                day_yield,
                day_yield_rate,
                day_fee,
            ) = account_yield[current_account]

            worksheet_holding[f"E{row_num}"].value = "现金"
            worksheet_holding[f"N{row_num}"].value = balance_hkd
            worksheet_holding[f"O{row_num}"].value = balance_ratio
            row_num += 1

            worksheet_holding[f"E{row_num}"].value = "美股"
            worksheet_holding[f"N{row_num}"].value = stock_us_hkd
            worksheet_holding[f"O{row_num}"].value = stock_us_ratio
            row_num += 1

            worksheet_holding[f"E{row_num}"].value = "港股"
            worksheet_holding[f"N{row_num}"].value = stock_hk_hkd
            worksheet_holding[f"O{row_num}"].value = stock_hk_ratio
            row_num += 1

            worksheet_holding[f"E{row_num}"].value = "初始本金"
            worksheet_holding[f"N{row_num}"].value = init_asset_hkd
            row_num += 1

            worksheet_holding[f"E{row_num}"].value = "AUM"
            worksheet_holding[f"H{row_num}"].value = day_yield_rate
            worksheet_holding[f"I{row_num}"].value = day_yield
            worksheet_holding[f"J{row_num}"].value = ytd_yield_rate
            worksheet_holding[f"K{row_num}"].value = ytd_yield
            worksheet_holding[f"L{row_num}"].value = acc_yield_rate
            worksheet_holding[f"M{row_num}"].value = acc_yield
            worksheet_holding[f"N{row_num}"].value = end_asset_hkd
            row_num += 1

            worksheet_holding[f"E{row_num}"].value = "手续费"
            worksheet_holding[f"I{row_num}"].value = day_fee
            worksheet_holding[f"K{row_num}"].value = ytd_fee
            worksheet_holding[f"M{row_num}"].value = acc_fee

            worksheet_holding.merge_cells(
                f"A{current_account_begin_row_num}:A{row_num}"
            )
            worksheet_holding[f"A{current_account_begin_row_num}"].alignment = center
            worksheet_holding.merge_cells(
                f"B{current_account_begin_row_num}:B{row_num}"
            )
            worksheet_holding[f"B{current_account_begin_row_num}"].alignment = center
            worksheet_holding.merge_cells(
                f"C{current_account_begin_row_num}:C{row_num}"
            )
            worksheet_holding[f"C{current_account_begin_row_num}"].alignment = center
            worksheet_holding.merge_cells(
                f"D{current_account_begin_row_num}:D{row_num}"
            )
            worksheet_holding[f"D{current_account_begin_row_num}"].alignment = center
            row_num += 1

            worksheet_holding[f"A{row_num}"] = " "
            row_num += 1

            worksheet_holding.append(header_cells)
            row_num += 1

            current_account = account_no
            current_account_begin_row_num = row_num

        worksheet_holding[f"A{row_num}"].value = asof_date
        worksheet_holding[f"B{row_num}"].value = portfolio_id
        worksheet_holding[f"C{row_num}"].value = portfolio_name
        worksheet_holding[f"D{row_num}"].value = account_no
        worksheet_holding[f"E{row_num}"].value = security_code
        worksheet_holding[f"F{row_num}"].value = security_name
        worksheet_holding[f"G{row_num}"].value = quantity
        worksheet_holding[f"N{row_num}"].value = market_value_hkd
        worksheet_holding[f"O{row_num}"].value = market_value_ratio
        row_num += 1

    if current_account is not None:
        init_asset_hkd = float(account_init_asset.get(current_account, 0))
        (
            balance_hkd,
            stock_us_hkd,
            stock_hk_hkd,
            end_asset_hkd,
            balance_ratio,
            stock_us_ratio,
            stock_hk_ratio,
        ) = account_end_asset[current_account]
        (
            _,
            _,
            acc_yield,
            acc_yield_rate,
            acc_fee,
            _,
            _,
            ytd_yield,
            ytd_yield_rate,
            ytd_fee,
            _,
            _,
            day_yield,
            day_yield_rate,
            day_fee,
        ) = account_yield[current_account]

        worksheet_holding[f"E{row_num}"].value = "现金"
        worksheet_holding[f"N{row_num}"].value = balance_hkd
        worksheet_holding[f"O{row_num}"].value = balance_ratio
        row_num += 1

        worksheet_holding[f"E{row_num}"].value = "美股"
        worksheet_holding[f"N{row_num}"].value = stock_us_hkd
        worksheet_holding[f"O{row_num}"].value = stock_us_ratio
        row_num += 1

        worksheet_holding[f"E{row_num}"].value = "港股"
        worksheet_holding[f"N{row_num}"].value = stock_hk_hkd
        worksheet_holding[f"O{row_num}"].value = stock_hk_ratio
        row_num += 1

        worksheet_holding[f"E{row_num}"].value = "初始本金"
        worksheet_holding[f"N{row_num}"].value = init_asset_hkd
        row_num += 1

        worksheet_holding[f"E{row_num}"].value = "AUM"
        worksheet_holding[f"H{row_num}"].value = day_yield_rate
        worksheet_holding[f"H{row_num}"].number_format = excel_percent_fmt
        worksheet_holding[f"I{row_num}"].value = day_yield
        worksheet_holding[f"J{row_num}"].value = ytd_yield_rate
        worksheet_holding[f"K{row_num}"].value = ytd_yield
        worksheet_holding[f"L{row_num}"].value = acc_yield_rate
        worksheet_holding[f"M{row_num}"].value = acc_yield
        worksheet_holding[f"N{row_num}"].value = end_asset_hkd
        row_num += 1

        worksheet_holding[f"E{row_num}"].value = "手续费"
        worksheet_holding[f"I{row_num}"].value = day_fee
        worksheet_holding[f"K{row_num}"].value = ytd_fee
        worksheet_holding[f"M{row_num}"].value = acc_fee

        worksheet_holding.merge_cells(f"A{current_account_begin_row_num}:A{row_num}")
        worksheet_holding[f"A{current_account_begin_row_num}"].alignment = center
        worksheet_holding.merge_cells(f"B{current_account_begin_row_num}:B{row_num}")
        worksheet_holding[f"B{current_account_begin_row_num}"].alignment = center
        worksheet_holding.merge_cells(f"C{current_account_begin_row_num}:C{row_num}")
        worksheet_holding[f"C{current_account_begin_row_num}"].alignment = center
        worksheet_holding.merge_cells(f"D{current_account_begin_row_num}:D{row_num}")
        worksheet_holding[f"D{current_account_begin_row_num}"].alignment = center

        for row in worksheet_holding.iter_rows():
            for cell in row:
                cell.border = border

        for col in worksheet_holding.iter_cols(min_col=8, max_col=15):
            for cell in col:
                if cell.column_letter in ("H", "J", "L", "O"):
                    cell.number_format = excel_percent_fmt
                elif cell.column_letter in ("I", "K", "M", "N"):
                    cell.number_format = excel_number_fmt

    workbook.save(result_file_path)


def generate_tonghuashun_revenue_cost(p_end_date: date, result_file_path: str) -> None:
    """生成同花顺佣金活动成本数据Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/channel_settle/tonghuashun_revenue_cost_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    sql_query = get_file_content("sql/ads/channel_settle/tonghuashun_revenue_cost.sql")
    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    p_begin_date = date(p_end_date.year, p_end_date.month, 1)

    (
        hk_commission_hkd,
        us_commission_hkd,
        all_commission_hkd,
        broker_cost_hkd,
        activity_cost_hkd,
        channel_cost_hkd,
        retain_revenue_hkd,
    ) = ads_hook.get_first(
        sql_query.format(
            p_begin_date=p_begin_date.isoformat(), p_end_date=p_end_date.isoformat()
        )
    )

    worksheet["A2"].value = p_end_date.strftime("%Y.%m")
    worksheet["B2"].value = round(hk_commission_hkd, 2)
    worksheet["C2"].value = round(us_commission_hkd, 2)
    worksheet["D2"].value = round(all_commission_hkd, 2)
    worksheet["E2"].value = round(broker_cost_hkd, 2)
    worksheet["F2"].value = round(activity_cost_hkd, 2)
    worksheet["G2"].value = round(channel_cost_hkd, 2)
    worksheet["H2"].value = round(retain_revenue_hkd, 2)

    workbook.save(result_file_path)


def generate_public_fund_management_subred_fee(
    p_begin_date: date, p_end_date: date, result_file_path: str
) -> None:
    """生成非货币基金管理费申赎费Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/wealth_report/public_fund_management_subred_fee_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    sql_query = get_file_content(
        "sql/ads/wealth_report/public_fund_management_subred_fee.sql"
    )
    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    row_num = 2
    for (
        trade_date,
        currency_code,
        exchange_code,
        fund_type,
        security_code,
        platform,
        custodian,
        manager_cn,
        fund_manager,
        fund_name_english,
        fund_name_chinese,
        account_no,
        account_name_english,
        ae_code,
        ae_name,
        market_value,
        market_value_hkd,
        holding_commission_hkd,
        sub_red_fee_hkd,
    ) in ads_hook.get_records(
        sql_query.format(
            p_begin_date=p_begin_date.isoformat(), p_end_date=p_end_date.isoformat()
        )
    ):
        worksheet[f"A{row_num}"].value = trade_date
        worksheet[f"B{row_num}"].value = currency_code
        worksheet[f"C{row_num}"].value = exchange_code
        worksheet[f"D{row_num}"].value = fund_type
        worksheet[f"E{row_num}"].value = security_code
        worksheet[f"F{row_num}"].value = platform
        worksheet[f"G{row_num}"].value = custodian
        worksheet[f"H{row_num}"].value = manager_cn
        worksheet[f"I{row_num}"].value = fund_manager
        worksheet[f"J{row_num}"].value = fund_name_english
        worksheet[f"K{row_num}"].value = fund_name_chinese
        worksheet[f"L{row_num}"].value = account_no
        worksheet[f"M{row_num}"].value = account_name_english
        worksheet[f"N{row_num}"].value = ae_code
        worksheet[f"O{row_num}"].value = ae_name
        worksheet[f"P{row_num}"].value = market_value
        worksheet[f"Q{row_num}"].value = market_value_hkd
        worksheet[f"R{row_num}"].value = holding_commission_hkd
        worksheet[f"S{row_num}"].value = sub_red_fee_hkd
        row_num += 1

    workbook.save(result_file_path)


def generate_b1_channel_deposit_withdraw_stats(
    p_begin_date: date, p_end_date: date, result_file_path: str
) -> None:
    """生成互财渠道入金数据报表Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/operation_explore/b1_channel_deposit_withdraw_stats_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    sql_query = get_file_content(
        "sql/ads/operation_explore/b1_channel_deposit_withdraw_stats.sql"
    )
    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    row_num = 2
    for (
        open_date,
        ae_code,
        level1_channel,
        level2_channel,
        client_name,
        account_no,
        phone,
        first_deposit_value_hkd,
        total_deposit_hkd,
        first_deposit_date,
        first_withdraw_date,
        retain_30d_net_deposit_1w,
        has_stock_trade,
        first_stock_trade_date,
        first_stock_trade_name,
    ) in ads_hook.get_records(
        sql_query.format(
            p_begin_date=p_begin_date.isoformat(), p_end_date=p_end_date.isoformat()
        )
    ):
        worksheet[f"A{row_num}"].value = open_date
        worksheet[f"B{row_num}"].value = ae_code
        worksheet[f"C{row_num}"].value = level1_channel
        worksheet[f"D{row_num}"].value = level2_channel
        worksheet[f"E{row_num}"].value = client_name
        worksheet[f"F{row_num}"].value = account_no
        worksheet[f"G{row_num}"].value = phone
        worksheet[f"H{row_num}"].value = first_deposit_value_hkd
        worksheet[f"I{row_num}"].value = total_deposit_hkd
        worksheet[f"J{row_num}"].value = first_deposit_date
        worksheet[f"K{row_num}"].value = first_withdraw_date
        worksheet[f"L{row_num}"].value = retain_30d_net_deposit_1w
        worksheet[f"M{row_num}"].value = has_stock_trade
        worksheet[f"N{row_num}"].value = first_stock_trade_date
        worksheet[f"O{row_num}"].value = first_stock_trade_name
        row_num += 1

    workbook.save(result_file_path)


def generate_discretionary_account_info(
    p_end_date: date, result_file_path: str
) -> None:
    """生成全权委托账户信息Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/misc/discretionary_account_info_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Data"]

    sql_query = get_file_content("sql/ads/misc/discretionary_account_info.sql")
    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    row_num = 2
    for (
        name_chinese,
        name_english,
        account_no,
        main_account_no,
        account_type,
        open_date,
        account_status,
        close_date,
        suspend_status,
        mtd_has_trade,
        aml_risk_level,
        t6m_no_asset,
        rel_staff,
        is_worldfirst_payoneer,
        consultant_name,
    ) in ads_hook.get_records(sql_query.format(p_end_date=p_end_date.isoformat())):
        worksheet[f"A{row_num}"].value = name_chinese
        worksheet[f"B{row_num}"].value = name_english
        worksheet[f"C{row_num}"].value = account_no
        worksheet[f"D{row_num}"].value = main_account_no
        worksheet[f"E{row_num}"].value = account_type
        worksheet[f"F{row_num}"].value = open_date
        worksheet[f"G{row_num}"].value = account_status
        worksheet[f"H{row_num}"].value = close_date
        worksheet[f"I{row_num}"].value = suspend_status
        worksheet[f"J{row_num}"].value = mtd_has_trade
        worksheet[f"K{row_num}"].value = aml_risk_level
        worksheet[f"L{row_num}"].value = t6m_no_asset
        worksheet[f"M{row_num}"].value = is_worldfirst_payoneer
        worksheet[f"N{row_num}"].value = rel_staff
        worksheet[f"O{row_num}"].value = consultant_name
        row_num += 1

    workbook.save(result_file_path)


def generate_aimless_cash_movement(p_end_date: date, result_file_path: str) -> None:
    """生成全权委托账户信息Excel文件"""

    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/compliance/aimless_cash_movement_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)

    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    # 1. 停留少于48小时
    worksheet_short_stay = workbook["停留少于48小时"]
    sql_short_stay = get_file_content(
        "sql/ads/compliance/aimless_cash_movement_01_short_stay.sql"
    )

    res = ads_hook.get_records(sql_short_stay.format(p_end_date=p_end_date.isoformat()))
    if not res:
        worksheet_short_stay["A2"].value = "无"
    else:
        row_num = 2
        for (
            account_no,
            default_ae_code,
            account_type_desc,
            open_date,
            name_chinese,
            name_english,
            apply_date,
            complete_date,
            movement_type_desc,
            bank_account_name,
            bank_account_no,
            is_same_name,
            currency_code,
            amount,
        ) in res:
            worksheet_short_stay[f"A{row_num}"].value = account_no
            worksheet_short_stay[f"B{row_num}"].value = default_ae_code
            worksheet_short_stay[f"C{row_num}"].value = account_type_desc
            worksheet_short_stay[f"D{row_num}"].value = open_date
            worksheet_short_stay[f"E{row_num}"].value = name_chinese
            worksheet_short_stay[f"F{row_num}"].value = name_english
            worksheet_short_stay[f"G{row_num}"].value = apply_date
            worksheet_short_stay[f"H{row_num}"].value = complete_date
            worksheet_short_stay[f"I{row_num}"].value = movement_type_desc
            worksheet_short_stay[f"J{row_num}"].value = bank_account_name
            worksheet_short_stay[f"K{row_num}"].value = bank_account_no
            worksheet_short_stay[f"L{row_num}"].value = is_same_name
            worksheet_short_stay[f"M{row_num}"].value = currency_code
            worksheet_short_stay[f"N{row_num}"].value = amount
            row_num += 1

    # 2. 近5日频繁存取
    worksheet_frequent_operate = workbook["近5日频繁存取"]
    sql_frequent_operate = get_file_content(
        "sql/ads/compliance/aimless_cash_movement_02_frequent_operate.sql"
    )

    res = ads_hook.get_records(
        sql_frequent_operate.format(p_end_date=p_end_date.isoformat())
    )
    if not res:
        worksheet_frequent_operate["A2"].value = "无"
    else:
        row_num = 2
        for (
            account_no,
            default_ae_code,
            account_type_desc,
            open_date,
            name_chinese,
            name_english,
            apply_date,
            complete_date,
            movement_type_desc,
            bank_account_name,
            bank_account_no,
            is_same_name,
            currency_code,
            amount,
        ) in res:
            worksheet_frequent_operate[f"A{row_num}"].value = account_no
            worksheet_frequent_operate[f"B{row_num}"].value = default_ae_code
            worksheet_frequent_operate[f"C{row_num}"].value = account_type_desc
            worksheet_frequent_operate[f"D{row_num}"].value = open_date
            worksheet_frequent_operate[f"E{row_num}"].value = name_chinese
            worksheet_frequent_operate[f"F{row_num}"].value = name_english
            worksheet_frequent_operate[f"G{row_num}"].value = apply_date
            worksheet_frequent_operate[f"H{row_num}"].value = complete_date
            worksheet_frequent_operate[f"I{row_num}"].value = movement_type_desc
            worksheet_frequent_operate[f"J{row_num}"].value = bank_account_name
            worksheet_frequent_operate[f"K{row_num}"].value = bank_account_no
            worksheet_frequent_operate[f"L{row_num}"].value = is_same_name
            worksheet_frequent_operate[f"M{row_num}"].value = currency_code
            worksheet_frequent_operate[f"N{row_num}"].value = amount
            row_num += 1

    workbook.save(result_file_path)


def generate_ads_coupon_use_amount_by_aecode_type_m(
    p_begin_date: date, p_end_date: date, result_file_path: str
):
    """生成每月卡卷使用情况报表结果Excel文件"""

    # 模板路径配置
    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/operation_explore/ads_coupon_use_amount_by_aecode_type_m.xlsx",
    )

    #  加载模板
    workbook = openpyxl.load_workbook(excel_template)
    worksheet = workbook["Sheet1"]

    # 格式设置
    excel_number_fmt = "#,##0.00"

    # 连接ClickHouse
    ads_hook = clickhouse.ClickHouseHook(mysql_conn_id="ads")

    # 准备SQL查询
    sql_query = get_file_content(
        "sql/ads/operation_explore/ads_coupon_use_amount_by_aecode_type_m.sql"
    )

    # 格式化参数
    formatted_sql = sql_query.format(
        p_begin_date=p_begin_date.isoformat(),
        p_end_date=p_end_date.isoformat(),
    )

    # 获取数据并填充Excel 第二行
    row_num = 2

    # 获取数据
    records = ads_hook.get_records(formatted_sql)

    # 列位置映射
    column_mapping = {"ae_code": "A", "coupon_type_desc": "B", "use_amount_hkd": "C"}

    for record in records:
        # 提取字段值
        ae_code, coupon_type_desc, use_amount_hkd = record

        # 填值
        worksheet[f"{column_mapping['ae_code']}{row_num}"].value = ae_code
        worksheet[
            f"{column_mapping['coupon_type_desc']}{row_num}"
        ].value = coupon_type_desc

        # 设置金额格式
        worksheet[f"{column_mapping['use_amount_hkd']}{row_num}"].value = use_amount_hkd
        if use_amount_hkd is not None:
            worksheet[
                f"{column_mapping['use_amount_hkd']}{row_num}"
            ].number_format = excel_number_fmt

        row_num += 1

    # 保存结果文件
    workbook.save(result_file_path)





def generate_open_account_reject_report(
    p_begin_date: date, p_end_date:date, result_file_path: str
) -> None:
    """生成每日开户及驳回明细Excel文件"""
    #加载模板
    excel_template = os.path.join(
        airflow.configuration.get_airflow_home(),
        "sql/ads/customer_service/open_account_reject_detail_template.xlsx",
    )
    workbook = openpyxl.load_workbook(excel_template)

    #数据源为ods
    ads_hook = MySqlHook(mysql_conn_id="ods_uc")

    #周期：上周五-本周四
    # p_begin_date = (
    #                     begin_date - timedelta(days=7)
    #                 )  # 上周五
    # p_end_date = begin_date - timedelta(days=1)

#1.汇总数据
    row_num = 2
    worksheet_summary = workbook["汇总"]
    
    sql_query_summary = get_file_content(
        "sql/ads/customer_service/open_account_reject_summary.sql"
    )

    for (
        audit_date,
        open_acc_num,
        fake_proved_num,
        douc_unmatched_num,
        else_num,
        rate,
    ) in ads_hook.get_records(
        sql_query_summary.format(
            p_begin_date=p_begin_date.isoformat(),p_end_date=p_end_date.isoformat()
            
        )
    ):
        worksheet_summary[f"A{row_num}"].value = audit_date
        worksheet_summary[f"B{row_num}"].value = open_acc_num
        worksheet_summary[f"C{row_num}"].value = fake_proved_num
        worksheet_summary[f"D{row_num}"].value = douc_unmatched_num
        worksheet_summary[f"E{row_num}"].value = else_num
        worksheet_summary[f"F{row_num}"].value = rate
        row_num += 1

    
    #2.明细数据
    row_num = 2
    worksheet = workbook["明细"]
    sql_query = get_file_content(
        "sql/ads/customer_service/open_account_reject_detail.sql"
    )

    for (
        audit_date,
        hlId,
        phone,
        chineseName,
        aeCode,
        first_submittime_str,
        audit_step,
        audit_result,
        open_time_str,
        account_no,
        status_name,
        reject_reason,
        category,
    ) in ads_hook.get_records(
        sql_query.format(
            p_begin_date=p_begin_date.isoformat(),p_end_date=p_end_date.isoformat()
            
        )
    ):
        worksheet[f"A{row_num}"].value = audit_date
        worksheet[f"B{row_num}"].value = hlId
        worksheet[f"C{row_num}"].value = phone
        worksheet[f"D{row_num}"].value = chineseName
        worksheet[f"E{row_num}"].value = aeCode
        worksheet[f"F{row_num}"].value = first_submittime_str
        worksheet[f"G{row_num}"].value = audit_step
        worksheet[f"H{row_num}"].value = audit_result
        worksheet[f"I{row_num}"].value = open_time_str
        worksheet[f"J{row_num}"].value = account_no
        worksheet[f"K{row_num}"].value = status_name
        worksheet[f"L{row_num}"].value = reject_reason
        worksheet[f"M{row_num}"].value = category
        row_num += 1


    workbook.save(result_file_path) 









