from __future__ import annotations

import argparse
from pathlib import Path
from typing import Any

from evals.analyze_results import (
    _derive_case_condition_rows,
    _load_and_group_records,
    _print_input_errors,
    _summarize_bucket,
)


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(
        description="Print a concise eval summary for one run_id with strict schema-3 validation."
    )
    parser.add_argument("run_id", help="Run id (expects <results-dir>/<run_id>.jsonl).")
    parser.add_argument(
        "--results-dir",
        default="evals/results",
        help="Directory containing eval result JSONL files (default: evals/results).",
    )
    args = parser.parse_args(argv)

    results_path = Path(str(args.results_dir)) / f"{args.run_id}.jsonl"
    if not results_path.is_file():
        print(f"Input error: results file not found: {results_path}")
        return 1

    try:
        grouped, input_errors = _load_and_group_records([str(results_path)], strict_input=True)
    except ValueError as exc:
        print(f"Input error: {exc}")
        return 2

    if not grouped:
        _print_input_errors(input_errors)
        print("No records found.")
        return 1

    rows = _derive_case_condition_rows(grouped)
    if not rows:
        print("No valid case-condition records found.")
        return 1

    overall = _summarize_bucket(rows)
    _print_core_summary(
        run_id_requested=str(args.run_id),
        results_path=results_path,
        rows=rows,
        overall=overall,
        input_errors=input_errors,
    )
    return 0


def _print_core_summary(
    *,
    run_id_requested: str,
    results_path: Path,
    rows: list[dict[str, Any]],
    overall: dict[str, Any],
    input_errors: dict[str, int],
) -> None:
    run_ids = sorted({str(row.get("run_id") or "") for row in rows if row.get("run_id")})
    condition_matrix = _condition_matrix(overall)
    conditions = [str(item.get("condition") or "") for item in condition_matrix]
    adaptive_condition, adaptive_stats = _select_adaptive_stats(condition_matrix)

    print("Run Summary")
    print(f"- requested run_id: {run_id_requested}")
    print(f"- results file: {results_path}")
    print(f"- run IDs present: {', '.join(run_ids) if run_ids else 'n/a'}")
    print(f"- conditions: {', '.join(conditions) if conditions else 'none'}")
    print(f"- case-condition rows: {len(rows)}")

    print("\nCondition Effectiveness & Efficiency")
    if not condition_matrix:
        print("- none")
    for stats in condition_matrix:
        _print_condition_row(stats)

    print("\nPairwise Uplift Matrix")
    pairwise = _pairwise_uplifts(overall)
    if not pairwise:
        print("- none")
    else:
        for entry in pairwise:
            condition_a = str(entry.get("condition_a") or "?")
            condition_b = str(entry.get("condition_b") or "?")
            uplift = _fmt_signed_percent(entry.get("uplift_success_rate"))
            print(f"- {condition_a} -> {condition_b}: {uplift}")

    print("\nReliability & Input Quality")
    patch_attempts = int(overall.get("patch_attempts") or 0)
    test_touch_attempts = int(overall.get("test_touch_attempts") or 0)
    print(
        f"- test-touch patches: {test_touch_attempts}/{patch_attempts} "
        f"({_fmt_percent(overall.get('test_touch_attempt_rate'))})"
    )
    print(f"- stage-a request success rate: {_fmt_percent(overall.get('stage_a_request_success_rate'))}")
    print(f"- retry gate block rate: {_fmt_percent(overall.get('retry_gate_block_rate'))}")
    print(
        f"- retry history truncation rate: "
        f"{_fmt_percent(overall.get('retry_history_truncation_rate'))}"
    )
    print(
        "- input diagnostics: "
        f"files_unreadable={int(input_errors.get('files_unreadable', 0))}, "
        f"json_lines_invalid={int(input_errors.get('json_lines_invalid', 0))}, "
        f"records_skipped={int(input_errors.get('records_skipped', 0))}, "
        f"duplicate_attempt_rows_seen={int(input_errors.get('duplicate_attempt_rows_seen', 0))}, "
        f"duplicate_attempt_rows_resolved={int(input_errors.get('duplicate_attempt_rows_resolved', 0))}"
    )

    if _has_adaptive_condition(conditions) and adaptive_stats is not None:
        print(f"\nAdaptive Signals ({adaptive_condition})")
        print(
            "- helper: "
            f"invocation_case_rate={_fmt_percent(adaptive_stats.get('helper_invocation_case_rate'))}, "
            "invocation_attempt_rate="
            f"{_fmt_percent(adaptive_stats.get('helper_invocation_attempt_rate'))}, "
            f"success_when_invoked={_fmt_percent(adaptive_stats.get('helper_success_when_invoked'))}, "
            f"rescue_rate={_fmt_percent(adaptive_stats.get('helper_rescue_rate'))}"
        )
        print(
            "- online policy: "
            f"decisions={int(adaptive_stats.get('adaptive_online_decisions') or 0)}, "
            "selected_invoke_rate="
            f"{_fmt_percent(adaptive_stats.get('adaptive_online_selected_invoke_rate'))}, "
            "applied_invoke_rate="
            f"{_fmt_percent(adaptive_stats.get('adaptive_online_applied_invoke_rate'))}, "
            f"update_rate={_fmt_percent(adaptive_stats.get('adaptive_online_update_rate'))}, "
            f"mean_reward={_fmt_num(adaptive_stats.get('adaptive_online_mean_reward'))}, "
            f"mean_propensity={_fmt_num(adaptive_stats.get('adaptive_online_mean_propensity'))}"
        )

    print("\nControls & Guardrails")
    controls_source = adaptive_stats if adaptive_stats is not None else overall
    print(
        "- budget top-up: "
        f"case_rate={_fmt_percent(controls_source.get('adaptive_budget_topup_case_rate'))}, "
        f"attempt_rate={_fmt_percent(controls_source.get('adaptive_budget_topup_attempt_rate'))}"
    )
    print(
        "- syntax preflight: "
        f"failed_attempt_rate={_fmt_percent(controls_source.get('syntax_preflight_failed_attempt_rate'))}, "
        f"failures={int(controls_source.get('syntax_preflight_failures') or 0)}"
    )
    print(
        "- patch verifier source-scope match rate: "
        f"{_fmt_percent(controls_source.get('patch_verifier_source_scope_match_rate'))}"
    )
    print(
        "- helper guardrails: "
        f"budget_exhausted_rate={_fmt_percent(controls_source.get('helper_budget_exhausted_rate'))}, "
        f"saturation_guard_rate={_fmt_percent(controls_source.get('helper_saturation_guard_rate'))}"
    )


def _print_condition_row(stats: dict[str, Any]) -> None:
    condition = str(stats.get("condition") or "unknown")
    cases = int(stats.get("cases") or 0)
    successes = int(stats.get("successes") or 0)
    print(
        f"- {condition}: {successes}/{cases} ({_fmt_percent(stats.get('success_rate'))}), "
        f"median_attempts={_fmt_num(stats.get('median_attempts_to_success'))}, "
        f"mean_tokens_total={_fmt_num(stats.get('mean_tokens_total'))}, "
        f"mean_llm_calls={_fmt_num(stats.get('mean_llm_calls_per_case'))}, "
        f"mean_runtime_sec={_fmt_num(stats.get('mean_runtime_sec'))}"
    )


def _condition_matrix(overall: dict[str, Any]) -> list[dict[str, Any]]:
    raw = overall.get("condition_matrix")
    if not isinstance(raw, list):
        return []
    return [item for item in raw if isinstance(item, dict)]


def _pairwise_uplifts(overall: dict[str, Any]) -> list[dict[str, Any]]:
    raw = overall.get("pairwise_uplifts")
    if not isinstance(raw, list):
        return []
    return [item for item in raw if isinstance(item, dict)]


def _has_adaptive_condition(conditions: list[str]) -> bool:
    return any(condition.startswith("adaptive_") for condition in conditions)


def _select_adaptive_stats(
    condition_matrix: list[dict[str, Any]],
) -> tuple[str | None, dict[str, Any] | None]:
    stats_by_condition: dict[str, dict[str, Any]] = {}
    for item in condition_matrix:
        condition = str(item.get("condition") or "")
        if condition:
            stats_by_condition[condition] = item
    for preferred in ("adaptive_llm_discretion", "adaptive_gated"):
        if preferred in stats_by_condition:
            return preferred, stats_by_condition[preferred]
    for condition, stats in sorted(stats_by_condition.items()):
        if condition.startswith("adaptive_"):
            return condition, stats
    return None, None


def _fmt_percent(value: Any) -> str:
    if not isinstance(value, (int, float)):
        return "n/a"
    return f"{100.0 * float(value):.1f}%"


def _fmt_signed_percent(value: Any) -> str:
    if not isinstance(value, (int, float)):
        return "n/a"
    return f"{100.0 * float(value):+.1f}%"


def _fmt_num(value: Any) -> str:
    if not isinstance(value, (int, float)):
        return "n/a"
    value_float = float(value)
    value_int = int(value_float)
    if abs(value_float - value_int) < 1e-9:
        return str(value_int)
    return f"{value_float:.2f}"


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