"""kpi_causality 因果链验证机制迁移脚本 (2026-08-27 P2)

加列:
- source_type: varchar(20)  建链来源 AI_suggested/manual/imported
- verify_status: varchar(20) 验证状态 pending/data_verified/human_verified/disputed
- verified_at: datetime      验证时间
- verified_by: varchar(50)   验证人/AI/脚本
- entity_id: int             多租户隔离 (2026-08-27 收官补齐)

幂等: 列已存在则跳过; entity_id 回填只更新 NULL/0 行。
用法: python scripts/migrate_causality_verification.py
"""
import logging
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

from sqlalchemy import text

from app.database import get_engine

logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
logger = logging.getLogger("migrate-causality-verification")

COLUMNS = [
    ("source_type", "ALTER TABLE kpi_causality ADD COLUMN source_type VARCHAR(20) NOT NULL DEFAULT 'manual' COMMENT '建链来源 AI_suggested/manual/imported'"),
    ("verify_status", "ALTER TABLE kpi_causality ADD COLUMN verify_status VARCHAR(20) NOT NULL DEFAULT 'pending' COMMENT '验证状态 pending/data_verified/human_verified/disputed'"),
    ("verified_at", "ALTER TABLE kpi_causality ADD COLUMN verified_at DATETIME NULL COMMENT '验证时间'"),
    ("verified_by", "ALTER TABLE kpi_causality ADD COLUMN verified_by VARCHAR(50) NULL COMMENT '验证人/AI/脚本'"),
    ("entity_id", "ALTER TABLE kpi_causality ADD COLUMN entity_id INT NOT NULL DEFAULT 1 COMMENT '企业ID (多租户隔离 2026-08-27)'"),
]


def run():
    engine = get_engine()
    with engine.connect() as conn:
        # 1. 检查表是否存在
        exists = conn.execute(text(
            "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'kpi_causality'"
        )).scalar()
        if not exists:
            logger.error("kpi_causality 表不存在，跳过")
            return 1

        # 2. 现有列
        existing = {r[0] for r in conn.execute(text(
            "SELECT column_name FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'kpi_causality'"
        ))}
        logger.info("现有列: %s", sorted(existing))

        # 3. 加列（幂等）
        for col, ddl in COLUMNS:
            if col in existing:
                logger.info("列 %s 已存在，跳过", col)
            else:
                conn.execute(text(ddl))
                logger.info("已添加列 %s", col)

        # 4. 回填 entity_id（无条件从 source KPI 对齐，纠正默认值偏差）
        #    仅当来源KPI存在才回填；无来源KPI的孤儿链保持原值
        conn.execute(text(
            "UPDATE kpi_causality c JOIN kpi_definitions k ON k.id = c.source_kpi_id "
            "SET c.entity_id = k.entity_id"
        ))
        orphan = conn.execute(text(
            "SELECT COUNT(*) FROM kpi_causality c LEFT JOIN kpi_definitions k ON k.id = c.source_kpi_id "
            "WHERE k.id IS NULL"
        )).scalar()
        if orphan:
            logger.warning("%d 条因果链无来源KPI（孤儿链）", orphan)
        else:
            logger.info("entity_id 已全部按来源KPI回填")

        # 5. 验证
        cols = {r[0] for r in conn.execute(text(
            "SELECT column_name FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'kpi_causality'"
        ))}
        missing = {c for c, _ in COLUMNS} - cols
        if missing:
            logger.error("仍有缺失列: %s", missing)
            return 1
        row = conn.execute(text(
            "SELECT COUNT(*) FROM kpi_causality WHERE entity_id IS NULL OR entity_id = 0"
        )).scalar()
        if row:
            logger.error("仍有 %d 行 entity_id 为空", row)
            return 1
        total = conn.execute(text("SELECT COUNT(*) FROM kpi_causality")).scalar()
        logger.info("迁移完成: kpi_causality %d 条, 新列: source_type/verify_status/verified_at/verified_by/entity_id", total)
    return 0


if __name__ == "__main__":
    sys.exit(run())
