"""
   @Author      : hejiangming
   @Description : 品类调研"近一年分类月销峰值月"窄表导出：Hive dwt_bs_top100_last365_peak
                  → PG {site}_category_top_analysis_last365_peak。
                  PG 侧是普通表(不按月分区)：页面查任何月都 join 同一份最新结果，
                  每次导出用 copy 表 + exchange_tb 整表换入。
   @SourceTable : dwt_bs_top100_last365_peak (Hive, 分区 site_name/date_type/date_info)
   @SinkTable   : {site}_category_top_analysis_last365_peak (PG 集群, 正式表需手动建, DDL 见文件底部)
   @CreateTime  : 2026/08/03 11:29
   @UpdateTime  : 2026/08/03 11:29
"""
import os
import sys

sys.path.append(os.path.dirname(sys.path[0]))
from utils.ssh_util import SSHUtil
from utils.common_util import CommonUtil, DateTypes
from utils.db_util import DBUtil
from utils.hdfs_utils import HdfsUtils

if __name__ == '__main__':
    site_name = CommonUtil.get_sys_arg(1, None)
    date_type = CommonUtil.get_sys_arg(2, None)
    date_info = CommonUtil.get_sys_arg(3, None)
    # 最后一个参数判断是否导测试库
    test_flag = CommonUtil.get_sys_arg(len(sys.argv) - 1, None)
    print(f"执行参数为{sys.argv}")

    # 近一年滚动结果只有月粒度
    assert date_type == DateTypes.month.name, f"仅支持 month, 传入 date_type={date_type}"

    if test_flag == 'test':
        db_type = 'postgresql_test'
        print("导出到PG测试库中")
    else:
        # belonging_to_process 单独用"品类调研峰值月流程"，不并进"品类调研流程_month"：
        #   主表 + 同比环比两个导出走 modify_export_workflow_status，靠"同组未完成数=0"判断页面能否展示；
        #   本窄表若挂进同一组，会让那两个跑完时未完成数永远不为 0，主流程状态行写不出来。
        CommonUtil.judge_is_work_hours(site_name=site_name, date_type=date_type, date_info=date_info,
                                       principal='hejiangming', priority=2, export_tools_type=1,
                                       belonging_to_process=f'品类调研峰值月流程_{date_type}')
        db_type = 'postgresql_cluster'
        print("导出到PG集群库中")

    # 导出前校验 Hive 分区有数据：空分区会灌出一张空 copy 表，换表后线上直接没数据
    hive_path = CommonUtil.build_hdfs_path(
        "dwt_bs_top100_last365_peak",
        partition_dict={"site_name": site_name, "date_type": date_type, "date_info": date_info},
    )
    if not HdfsUtils.read_list(hive_path):
        print(f"[ERROR] Hive 分区无数据文件：{hive_path}，跳过导出，请先检查 DWT 计算任务！")
        sys.exit(1)
    print(f"Hive 分区有数据：{hive_path}，继续导出")

    export_tb_before = f"{site_name}_category_top_analysis_last365_peak"
    export_tb_rel = f"{export_tb_before}_copy"
    engine = DBUtil.get_db_engine(db_type, site_name)

    # 建 copy 表：结构 like 正式表(含 peak_month VARCHAR[])。
    # peak_month 正式表是 VARCHAR[]，sqoop 不能直写数组类型，先把 copy 的该列临时改成 VARCHAR 让 sqoop 写逗号串，
    # sqoop 完、换表前再 ALTER 回 VARCHAR[]（机制同 dwt_aba_last365_peak.py）。
    with engine.connect() as connection:
        sql = f"""
            drop table if exists {export_tb_rel};
            create table if not exists {export_tb_rel}
            (
                like {export_tb_before} including comments
            );
            ALTER TABLE {export_tb_rel} ALTER COLUMN peak_month TYPE VARCHAR(500);
        """
        print("================================执行sql================================")
        print(sql)
        connection.execute(sql)

    # 从 Hive 当前分区取 3 列写进 copy 表（列名与 Hive 表一致, sqoop 按名映射 PG 同名列）
    sh = CommonUtil.build_export_sh(
        site_name=site_name,
        db_type=db_type,
        hive_tb="dwt_bs_top100_last365_peak",
        export_tb=export_tb_rel,
        col=[
            "asin_node_current_id",
            "asin_node_parent_id_join",
            "peak_month",
        ],
        partition_dict={
            "site_name": site_name,
            "date_type": date_type,
            "date_info": date_info
        }
    )

    client = SSHUtil.get_ssh_client()
    SSHUtil.exec_command_async(client, sh, ignore_err=False)
    client.close()

    # 换表【前】把 copy 的 peak_month 从 VARCHAR 转回 VARCHAR[]（sqoop 写的逗号串拆成数组，
    #   如 "2025-11,2026-04" → {2025-11,2026-04}）。
    # 放在换表前：exchange_tb(cp_index_flag=True) 复制正式表索引时，列类型必须已经对上。
    with engine.connect() as connection:
        sql = f"""
            ALTER TABLE {export_tb_rel}
            ALTER COLUMN peak_month TYPE VARCHAR[]
            USING string_to_array(coalesce(peak_month, ''), ',')::varchar[];
        """
        print("================================执行sql================================")
        print(sql)
        connection.execute(sql)

    # 换表名：copy → 正式。cp_index_flag=True 自动把正式表现有索引复制到 copy 后再换入，
    #   索引靠"正式表建表时带好 → 每次换表自动传递"维护，无需手动重建。
    DBUtil.exchange_tb(engine,
                       source_tb_name=export_tb_rel,
                       target_tb_name=export_tb_before,
                       cp_index_flag=True)
    engine.dispose()

    # 更新 workflow_everyday：本窄表被页面直接查询，需单独上报导出完成供"数据就绪"监控感知。
    # 不走 modify_export_workflow_status（那是主表+同比环比"两个都完成才写"的机制，见上面 process 分组说明）。
    # page='CategoryTopPeak'(新增页面标识, 需同步给后端)；test 模式不写，避免污染监控。
    if test_flag != 'test':
        engine = DBUtil.get_db_engine("mysql", "us")
        with engine.connect() as connection:
            sql = f"""
                replace into workflow_everyday (
                    site_name, report_date, status, status_val, table_name, date_type, page, is_end, remark, export_db_type
                )
                values (
                    '{site_name}', '{date_info}', '导出pg完成', 14,
                    '{export_tb_before}', '{date_type}', '品类调研峰值月', '是',
                    '品类调研近一年月销峰值月窄表', 'postgresql_cluster'
                );
            """
            print("================================更新workflow_everyday================================")
            print(sql)
            connection.execute(sql)
        engine.dispose()

    print("success")

