#!/usr/bin/env python3
"""Phase 4 replacement pipeline orchestrator.

Default flow:
1) translate.py
2) optional glossary verification (low-confidence/full/off)
3) apply_glossary.py
4) polish.py
5) build_report.py
"""

from __future__ import annotations

import argparse
import json
import os
import subprocess
import sys
import time
from pathlib import Path


REPO_ROOT = Path(__file__).resolve().parent.parent
if str(REPO_ROOT) not in sys.path:
    sys.path.insert(0, str(REPO_ROOT))

from scripts.lib.markdown_chunker import split_by_headers


def resolve_project(arg: str) -> Path:
    p = Path(arg)
    if p.is_dir():
        return p.resolve()
    cand = REPO_ROOT / "projects" / arg
    if cand.is_dir():
        return cand.resolve()
    raise SystemExit(f"project not found: {arg}")


def run_step(cmd: list[str], *, dry_run: bool) -> int:
    print("$ " + " ".join(cmd))
    if dry_run:
        return 0
    return subprocess.run(cmd, cwd=REPO_ROOT, check=False).returncode


def infer_workers(source_file: Path, fallback: int, cap: int = 8) -> int:
    if not source_file.exists():
        return fallback
    text = source_file.read_text(encoding="utf-8")
    blocks = split_by_headers(text, max_level=2)
    if not blocks:
        return fallback
    cpu_cap = max(2, min(cap, (os.cpu_count() or 4)))
    suggested = max(2, min(cpu_cap, (len(blocks) + 5) // 6))
    return max(1, suggested if fallback <= 0 else min(max(fallback, 1), cpu_cap))


def low_confidence_terms(glossary_path: Path) -> list[str]:
    if not glossary_path.exists():
        return []
    try:
        glossary = json.loads(glossary_path.read_text(encoding="utf-8"))
    except Exception:
        return []
    out: list[str] = []
    for term, entry in glossary.items():
        if not isinstance(entry, dict):
            out.append(term)
            continue
        conf = str(entry.get("confidence", "")).lower()
        verified = bool(entry.get("verified_at"))
        if conf != "high" or not verified:
            out.append(term)
    return sorted(set(out))


def main() -> int:
    parser = argparse.ArgumentParser(description="Phase 4 replacement pipeline")
    parser.add_argument("project", help="Project slug or full path")
    parser.add_argument("--translate-model", default="anthropic/claude-sonnet-4.6")
    parser.add_argument("--glossary-model", default="anthropic/claude-haiku-4.5")
    parser.add_argument("--polish-model", default="anthropic/claude-sonnet-4.6")
    parser.add_argument("--translate-workers", type=int, default=0, help="0 means auto")
    parser.add_argument("--glossary-workers", type=int, default=4)
    parser.add_argument("--polish-workers", type=int, default=0, help="0 means auto")
    parser.add_argument(
        "--glossary-mode",
        choices=["off", "low-confidence", "full"],
        default="low-confidence",
        help="off: skip, low-confidence: verify only low-confidence terms, full: verify all",
    )
    parser.add_argument("--dry-run", action="store_true")
    args = parser.parse_args()

    project_root = resolve_project(args.project)
    phase4 = project_root / "phase4"
    src_en = phase4 / "final_en.md"
    if not src_en.exists():
        raise SystemExit(f"missing source: {src_en}")

    tw = infer_workers(src_en, args.translate_workers)
    zh = phase4 / "final_zh.md"
    pw = infer_workers(zh if zh.exists() else src_en, args.polish_workers)

    print(f"Project: {project_root.name}")
    print(f"Translate workers: {tw} | Polish workers: {pw}")
    print(f"Glossary mode: {args.glossary_mode}")
    print()

    t0 = time.time()
    steps: list[list[str]] = [
        [
            sys.executable,
            str(REPO_ROOT / "scripts" / "translate.py"),
            str(project_root),
            "--workers",
            str(tw),
            "--model",
            args.translate_model,
        ]
    ]

    if args.glossary_mode != "off":
        gcmd = [
            sys.executable,
            str(REPO_ROOT / "scripts" / "build_glossary.py"),
            str(project_root),
            "--workers",
            str(args.glossary_workers),
            "--model",
            args.glossary_model,
        ]
        if args.glossary_mode == "low-confidence":
            terms = low_confidence_terms(phase4 / "glossary.json")
            if terms:
                if len(terms) > 80:
                    print(f"[info] low-confidence terms={len(terms)} is large; fallback to full glossary verify")
                else:
                    gcmd += ["--only", ",".join(terms)]
            else:
                print("[info] no low-confidence glossary terms found; skipping glossary step")
                gcmd = []
        if gcmd:
            steps.append(gcmd)

    steps.extend(
        [
            [
                sys.executable,
                str(REPO_ROOT / "scripts" / "apply_glossary.py"),
                str(project_root),
                "--input",
                "phase4/final_zh.md",
            ],
            [
                sys.executable,
                str(REPO_ROOT / "scripts" / "polish.py"),
                str(project_root),
                "--workers",
                str(pw),
                "--model",
                args.polish_model,
            ],
            [
                sys.executable,
                str(REPO_ROOT / "scripts" / "build_report.py"),
                str(project_root),
            ],
        ]
    )

    for cmd in steps:
        rc = run_step(cmd, dry_run=args.dry_run)
        if rc != 0:
            return rc

    print(f"\nPhase 4 pipeline done in {time.time() - t0:.1f}s")
    return 0


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