"""
执行 2026-02-20 批次的所有迁移脚本到测试库（TEST_DB_DSN）。
按文件名排序依次执行，每个脚本执行后运行内嵌验证 SQL。
所有脚本均为幂等设计（IF NOT EXISTS / IF EXISTS）。
"""

import os
import sys
from pathlib import Path
from dotenv import load_dotenv
import psycopg2

load_dotenv(Path(__file__).resolve().parents[2] / ".env")

DSN = os.getenv("TEST_DB_DSN")
if not DSN:
    print("ERROR: TEST_DB_DSN 未配置")
    sys.exit(1)

MIGRATIONS_DIR = Path(__file__).resolve().parents[2] / "db" / "etl_feiqiu" / "migrations"

# 按顺序执行的迁移脚本（2026-02-20 批次）
SCRIPTS = sorted([
    f for f in MIGRATIONS_DIR.glob("2026-02-20__*.sql")
], key=lambda p: p.name)

def execute_migration(conn, script_path: Path) -> bool:
    """执行单个迁移脚本，返回是否成功"""
    name = script_path.name
    sql = script_path.read_text(encoding="utf-8")

    # 提取主体 SQL（去掉注释中的回滚和验证部分）
    # 找到第一个 "-- ===...回滚" 或文件末尾
    main_sql_lines = []
    in_rollback_or_verify = False
    for line in sql.split("\n"):
        stripped = line.strip()
        if stripped.startswith("-- ====") and ("回滚" in stripped or "ROLLBACK" in stripped.upper()):
            in_rollback_or_verify = True
        if stripped.startswith("-- ====") and "验证" in stripped:
            in_rollback_or_verify = True
        if not in_rollback_or_verify:
            main_sql_lines.append(line)

    main_sql = "\n".join(main_sql_lines).strip()
    if not main_sql:
        print(f"  ⚠️ {name}: 空脚本，跳过")
        return True

    try:
        # 对于包含 BEGIN/COMMIT 的脚本，需要 autocommit
        # 但 psycopg2 默认在事务中，我们直接执行即可
        # 注意：脚本内部已有 BEGIN/COMMIT，所以用 autocommit 模式
        old_autocommit = conn.autocommit
        conn.autocommit = True
        cur = conn.cursor()
        cur.execute(main_sql)
        cur.close()
        conn.autocommit = old_autocommit
        print(f"  ✅ {name}")
        return True
    except Exception as e:
        conn.rollback()
        print(f"  ❌ {name}: {e}")
        return False


def verify_all(conn):
    """执行迁移后的综合验证"""
    cur = conn.cursor()
    checks = []

    # 1. dim_assistant_ex 新增 4 列
    cur.execute("""
        SELECT column_name FROM information_schema.columns
        WHERE table_schema = 'dwd' AND table_name = 'dim_assistant_ex'
          AND column_name IN ('system_role_id', 'job_num', 'cx_unit_price', 'pd_unit_price')
        ORDER BY column_name
    """)
    cols = [r[0] for r in cur.fetchall()]
    checks.append(("dim_assistant_ex +4列", len(cols) == 4, cols))

    # 2. dwd_assistant_service_log_ex 新增 2 列
    cur.execute("""
        SELECT column_name FROM information_schema.columns
        WHERE table_schema = 'dwd' AND table_name = 'dwd_assistant_service_log_ex'
          AND column_name IN ('operator_id', 'operator_name')
        ORDER BY column_name
    """)
    cols = [r[0] for r in cur.fetchall()]
    checks.append(("dwd_assistant_service_log_ex +2列", len(cols) == 2, cols))

    # 3. dim_table_ex 新增 14 列
    cur.execute("""
        SELECT count(*) FROM information_schema.columns
        WHERE table_schema = 'dwd' AND table_name = 'dim_table_ex'
          AND column_name IN (
            'create_time', 'light_status', 'tablestatusname', 'sitename',
            'applet_qr_code_url', 'audit_status', 'charge_free', 'delay_lights_time',
            'is_rest_area', 'only_allow_groupon', 'order_delay_time', 'self_table',
            'temporary_light_second', 'virtual_table'
          )
    """)
    cnt = cur.fetchone()[0]
    checks.append(("dim_table_ex +14列", cnt == 14, f"{cnt}/14"))

    # 4. dwd_member_balance_change_ex.relate_id
    cur.execute("""
        SELECT column_name FROM information_schema.columns
        WHERE table_schema = 'dwd' AND table_name = 'dwd_member_balance_change_ex'
          AND column_name = 'relate_id'
    """)
    checks.append(("dwd_member_balance_change_ex +relate_id", cur.fetchone() is not None, ""))

    # 5. dim_store_goods_ex.batch_stock_quantity
    cur.execute("""
        SELECT column_name FROM information_schema.columns
        WHERE table_schema = 'dwd' AND table_name = 'dim_store_goods_ex'
          AND column_name = 'batch_stock_quantity'
    """)
    checks.append(("dim_store_goods_ex +batch_stock_quantity", cur.fetchone() is not None, ""))

    # 6. dwd_goods_stock_summary 表存在
    cur.execute("""
        SELECT 1 FROM information_schema.tables
        WHERE table_schema = 'dwd' AND table_name = 'dwd_goods_stock_summary'
    """)
    checks.append(("dwd_goods_stock_summary 已创建", cur.fetchone() is not None, ""))

    # 7. dwd_goods_stock_movement 表存在
    cur.execute("""
        SELECT 1 FROM information_schema.tables
        WHERE table_schema = 'dwd' AND table_name = 'dwd_goods_stock_movement'
    """)
    checks.append(("dwd_goods_stock_movement 已创建", cur.fetchone() is not None, ""))

    # 8. DWS 库存汇总 3 张表
    cur.execute("""
        SELECT table_name FROM information_schema.tables
        WHERE table_schema = 'dws' AND table_name LIKE 'dws_goods_stock_%_summary'
        ORDER BY table_name
    """)
    tables = [r[0] for r in cur.fetchall()]
    checks.append(("DWS 库存汇总 3 张表", len(tables) == 3, tables))

    # 9. dwd_store_goods_sale: discount_money + discount_price 两列
    cur.execute("""
        SELECT column_name FROM information_schema.columns
        WHERE table_schema = 'dwd' AND table_name = 'dwd_store_goods_sale'
          AND column_name IN ('discount_money', 'discount_price')
        ORDER BY column_name
    """)
    cols = [r[0] for r in cur.fetchall()]
    checks.append(("dwd_store_goods_sale discount_money+discount_price", len(cols) == 2, cols))

    # 10. settlement_ticket_details 已删除
    cur.execute("""
        SELECT 1 FROM information_schema.tables
        WHERE table_schema = 'ods' AND table_name = 'settlement_ticket_details'
    """)
    checks.append(("settlement_ticket_details 已删除", cur.fetchone() is None, ""))

    cur.close()

    print("\n" + "=" * 60)
    print("迁移验证结果")
    print("=" * 60)
    all_ok = True
    for name, ok, detail in checks:
        status = "✅" if ok else "❌"
        detail_str = f" → {detail}" if detail else ""
        print(f"  {status} {name}{detail_str}")
        if not ok:
            all_ok = False

    return all_ok


def main():
    print(f"连接测试库: {DSN.split('@')[1] if '@' in DSN else DSN}")
    print(f"迁移目录: {MIGRATIONS_DIR}")
    print(f"发现 {len(SCRIPTS)} 个 2026-02-20 迁移脚本\n")

    conn = psycopg2.connect(DSN)

    print("执行迁移:")
    success = 0
    failed = 0
    for script in SCRIPTS:
        if execute_migration(conn, script):
            success += 1
        else:
            failed += 1

    print(f"\n执行完成: {success} 成功, {failed} 失败")

    # 验证
    all_ok = verify_all(conn)
    conn.close()

    if not all_ok:
        print("\n⚠️ 部分验证未通过，请检查")
        sys.exit(1)
    else:
        print("\n✅ 所有迁移已成功执行并验证通过")


if __name__ == "__main__":
    main()
