#!/usr/bin/env python3
"""Generate propagation-fission drafts or publish an audited DB release."""

from __future__ import annotations

import argparse
import os
import sys
from datetime import datetime
from pathlib import Path

from dotenv import load_dotenv

HERE = Path(__file__).resolve().parent
ROOT = HERE.parents[1]
RTC_DIR = ROOT / "examples" / "tencent_realtime_control"
for path in (ROOT, HERE, RTC_DIR):
    if str(path) not in sys.path:
        sys.path.insert(0, str(path))
load_dotenv(HERE / ".env", override=False)
load_dotenv(Path.cwd() / ".env", override=False)

from logging_setup import setup_logging

from roi_control.fission_multiplier import (
    DEFAULT_FISSION_PARAMETER_VERSION,
    FISSION_HORIZON_DAYS,
    load_fission_multiplier_parameters,
    parameter_content_sha256,
    parameter_values,
    parameters_from_database,
)
from roi_control.fission_multiplier_refresh import (
    HORIZON,
    build_gzh_activity_curve_sql,
    build_miniapp_activity_curve_sql,
    build_qiwei_activity_curve_sql,
    write_draft_release,
    write_qiwei_draft,
)
from roi_control.odps_client import ODPSClient
from roi_control.repository import (
    load_fission_parameter_release,
    publish_fission_parameter_release,
)
from storage import initialize_schema


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="复算或发布传播裂变系数参数")
    mode = parser.add_mutually_exclusive_group(required=True)
    mode.add_argument("--cohort-date", help="YYYYMMDD，复算并生成参数草稿")
    mode.add_argument(
        "--publish-version",
        help=(
            "将已审计并登记SHA256的参数版本发布到MySQL；例如 "
            f"{DEFAULT_FISSION_PARAMETER_VERSION}"
        ),
    )
    parser.add_argument(
        "--output-dir",
        help="草稿输出目录；默认 outputs/roi_fission_drafts/<cohort-date>",
    )
    parser.add_argument(
        "--sql-only",
        action="store_true",
        help="只生成SQL，不查询ODPS",
    )
    parser.add_argument(
        "--published-by",
        default=os.getenv(
            "ROI_PARAMETER_PUBLISHED_BY",
            os.getenv("USER", "manual"),
        ),
        help="参数发布人或发布任务标识",
    )
    return parser


def publish_version(version: str, published_by: str) -> int:
    parameters = load_fission_multiplier_parameters(version)
    release = parameters.release
    metadata = parameters.snapshot()
    metadata["file_sha256"] = dict(release.file_sha256)
    initialize_schema()
    created = publish_fission_parameter_release(
        {
            "version": release.version,
            "cohort_date": datetime.strptime(release.cohort_date, "%Y%m%d").date(),
            "observation_end_date": datetime.strptime(
                release.observation_end_date, "%Y%m%d"
            ).date(),
            "horizon_days": FISSION_HORIZON_DAYS,
            "run_suffix": release.run_suffix,
            "content_sha256": parameter_content_sha256(parameters),
            "metadata": metadata,
        },
        parameter_values(parameters),
        published_by=published_by,
    )
    loaded = parameters_from_database(*load_fission_parameter_release(version))
    if parameter_content_sha256(loaded) != parameter_content_sha256(parameters):
        raise RuntimeError(f"传播裂变系数发布后回读校验失败: {version}")
    action = "发布完成" if created else "已存在且内容一致，跳过"
    print(
        f"参数{action}: version={version} values={len(parameter_values(parameters))}",
        flush=True,
    )
    return 0


def main() -> int:
    setup_logging(level=os.getenv("LOG_LEVEL", "INFO"))
    args = build_parser().parse_args()
    if args.publish_version:
        if args.sql_only:
            raise ValueError("--sql-only不能与--publish-version同时使用")
        return publish_version(args.publish_version, args.published_by)

    output_dir = Path(
        args.output_dir
        or f"outputs/roi_fission_drafts/{args.cohort_date}"
    ).expanduser().resolve()
    output_dir.mkdir(parents=True, exist_ok=True)

    miniapp_sql = build_miniapp_activity_curve_sql(args.cohort_date, HORIZON)
    gzh_sql = build_gzh_activity_curve_sql(args.cohort_date, HORIZON)
    qiwei_sql = build_qiwei_activity_curve_sql(args.cohort_date, HORIZON)
    miniapp_sql_path = output_dir / f"小程序人群包转化目标_A0-A15_{args.cohort_date}.sql"
    gzh_sql_path = output_dir / f"公众号合作即转_A0-A15_{args.cohort_date}.sql"
    qiwei_sql_path = output_dir / f"企微合作方_A0-A15_{args.cohort_date}.sql"
    miniapp_sql_path.write_text(miniapp_sql + "\n", encoding="utf-8")
    gzh_sql_path.write_text(gzh_sql + "\n", encoding="utf-8")
    qiwei_sql_path.write_text(qiwei_sql + "\n", encoding="utf-8")
    print(f"SQL已生成: {miniapp_sql_path}")
    print(f"SQL已生成: {gzh_sql_path}")
    print(f"SQL已生成: {qiwei_sql_path}")
    if args.sql_only:
        return 0

    client = ODPSClient()
    print("[1/3] 查询小程序 cohort", flush=True)
    miniapp_raw = client.execute_sql(miniapp_sql)
    print("[2/3] 查询公众号 cohort", flush=True)
    gzh_raw = client.execute_sql(gzh_sql)
    print("[3/3] 查询企微 cohort", flush=True)
    qiwei_raw = client.execute_sql(qiwei_sql)
    paths = write_draft_release(
        output_dir,
        args.cohort_date,
        miniapp_raw,
        gzh_raw,
    )
    qiwei_paths = write_qiwei_draft(
        output_dir,
        args.cohort_date,
        qiwei_raw,
    )
    print(
        f"草稿完成: 小程序={len(miniapp_raw)}行 公众号={len(gzh_raw)}行 "
        f"企微={len(qiwei_raw)}行 联合workbook={paths['workbook']} "
        f"企微workbook={qiwei_paths['workbook']}",
        flush=True,
    )
    print("提示: 草稿不会自动发布；审计后需登记版本和SHA256。", flush=True)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
