from __future__ import annotations

"""Compare baseline (no text) vs caption-fused runs. Compute Delta R@1 report.

Usage:
    python -m scripts.compare_runs \
        --baseline_report out/caption_test/baseline_no_text/eval_report.json \
        --full_report out/caption_test/balanced/eval_report.json \
        --output out/caption_test/comparison.md
"""

import argparse
import json
from pathlib import Path


_DIRECTIONS = (
    "query_to_gallery",
    "gallery_to_query",
)
_KS = (1, 5, 10)


def _load_metrics(report_path: Path) -> dict[str, float]:
    with report_path.open("r", encoding="utf-8") as f:
        data = json.load(f)
    return data.get("metrics", data)


def _format_row(name: str, baseline: dict[str, float], full: dict[str, float]) -> str:
    cells = [name]
    for k in _KS:
        key = f"r@{k}_{name}"
        b = baseline.get(key, float("nan"))
        f_ = full.get(key, float("nan"))
        delta = f_ - b if (b == b and f_ == f_) else float("nan")
        cells.append(f"{b:.4f} -> {f_:.4f} (D {delta:+.4f})")
    return "| " + " | ".join(cells) + " |"


def _interpret_delta(delta: float) -> str:
    if delta >= 0.03:
        return "PASS -- captions informative (D R@1 >= +3%)"
    if delta >= 0.01:
        return "MARGINAL -- consider VLM refinement (+1% <= D < +3%)"
    if delta >= 0:
        return "WEAK -- captions add little signal (< +1%)"
    return "HARMFUL -- captions confuse model (D < 0)"


def build_comparison_markdown(
    baseline: dict[str, float],
    full: dict[str, float],
) -> str:
    lines: list[str] = ["# Caption Quality Test: Comparison Report", ""]

    primary = "query_to_gallery"
    primary_key = f"r@1_{primary}"
    primary_delta = full.get(primary_key, 0.0) - baseline.get(primary_key, 0.0)
    verdict = _interpret_delta(primary_delta)

    lines.append(f"## Primary metric: D R@1 (query->gallery) = {primary_delta:+.4f}")
    lines.append("")
    lines.append(f"**Verdict:** {verdict}")
    lines.append("")

    # Gate value.
    gate = full.get("gate", None)
    if gate is not None:
        lines.append(f"**Fusion gate:** {gate:.4f} (1.0 = text ignored, 0.0 = image ignored)")
        lines.append("")

    lines.append("## All directions x K")
    lines.append("")
    header = "| Direction | R@1 base -> full | R@5 base -> full | R@10 base -> full |"
    sep = "|---|---|---|---|"
    lines.extend([header, sep])
    for direction in _DIRECTIONS:
        lines.append(_format_row(direction, baseline, full))
    lines.append("")

    lines.append("## Decision rule")
    lines.append("")
    lines.append("- D R@1 >= +3% -> captions pass, proceed to production")
    lines.append("- +1% <= D R@1 < +3% -> add VLM refinement, re-run")
    lines.append("- D R@1 < +1% -> redesign caption pipeline")
    lines.append("- D R@1 < 0 -> critical bug, investigate")
    lines.append("")

    return "\n".join(lines)


def main() -> None:
    parser = argparse.ArgumentParser(description="Compare baseline vs caption runs.")
    parser.add_argument("--baseline_report", type=Path, required=True)
    parser.add_argument("--full_report", type=Path, required=True)
    parser.add_argument("--output", type=Path, required=True)
    args = parser.parse_args()

    baseline = _load_metrics(args.baseline_report)
    full = _load_metrics(args.full_report)

    md = build_comparison_markdown(baseline=baseline, full=full)

    args.output.parent.mkdir(parents=True, exist_ok=True)
    with args.output.open("w", encoding="utf-8") as f:
        f.write(md)

    summary = {
        "baseline_metrics": baseline,
        "full_metrics": full,
        "deltas": {
            f"delta_r@{k}_{d}": (
                full.get(f"r@{k}_{d}", 0.0) - baseline.get(f"r@{k}_{d}", 0.0)
            )
            for d in _DIRECTIONS
            for k in _KS
        },
    }
    summary_path = args.output.with_suffix(".json")
    with summary_path.open("w", encoding="utf-8") as f:
        json.dump(summary, f, indent=2)

    print(f"Comparison saved: {args.output}")
    print(f"Summary saved:    {summary_path}")


if __name__ == "__main__":
    main()
