from __future__ import annotations

import argparse
import json
import os
import time
from pathlib import Path
from typing import Any

from policyfaultbench.conformance import evaluate_proposal_conformance
from policyfaultbench.models import ToolCall
from policyfaultbench.providers.gemini import GeminiAdapter
from policyfaultbench.scenarios import load_scenarios


GATE_SCENARIOS = (
    "S01-E",
    "S03-E",
    "S04-D",
    "S05-E",
    "S06-B",
    "S06-D",
    "S07-B",
    "S07-D",
    "S07-I",
    "S09-B",
    "S09-D",
    "S09-I",
)


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--root", type=Path, required=True)
    parser.add_argument("--output", type=Path, required=True)
    parser.add_argument("--delay-seconds", type=float, default=15.5)
    args = parser.parse_args()

    api_key = os.environ.get("GEMINI_API_KEY", "")
    if len(api_key) < 20:
        raise SystemExit("GEMINI_API_KEY is unavailable")
    config = json.loads(
        (args.root / "config" / "experiment.json").read_text(encoding="utf-8")
    )
    model = str(config["models"]["gemini"])
    adapter = GeminiAdapter(
        model,
        api_key,
        timeout_seconds=int(config["request_timeout_seconds"]),
    )
    scenarios = {
        item.scenario_id: item
        for item in load_scenarios(args.root / "scenarios" / "core_40.json")
    }

    results: list[dict[str, Any]] = []
    for index, scenario_id in enumerate(GATE_SCENARIOS):
        if index and args.delay_seconds:
            time.sleep(args.delay_seconds)
        scenario = scenarios[scenario_id]
        row: dict[str, Any] = {"scenario_id": scenario_id}
        try:
            response = adapter.propose(scenario)
            if len(response.proposals) != 1:
                raise ValueError("exactly one proposal is required")
            proposal = response.proposals[0]
            if proposal.name != "propose_action":
                raise ValueError("unexpected proposal name")
            raw = proposal.arguments
            call = ToolCall(
                subject=str(raw["subject"]),
                action=str(raw["action"]),
                resource=str(raw["resource"]),
                arguments=dict(raw.get("arguments", {})),
                context=dict(raw.get("context", {})),
                call_id=proposal.call_id,
            )
            result = evaluate_proposal_conformance(scenario, call)
            row.update(result.as_dict())
            row["input_tokens"] = response.input_tokens
            row["output_tokens"] = response.output_tokens
        except Exception as exc:
            row.update(
                {
                    "passed": False,
                    "mismatch_fields": ["provider_or_schema_error"],
                    "error_type": type(exc).__name__,
                }
            )
        results.append(row)

    failures = [row for row in results if not row.get("passed", False)]
    report = {
        "schema_version": "1.0",
        "gate_id": "gemini-schema-conformance-v1p1",
        "provider": "gemini",
        "model": model,
        "scenario_count": len(results),
        "passed": len(results) - len(failures),
        "failed": len(failures),
        "gate_passed": not failures,
        "results": results,
    }
    args.output.parent.mkdir(parents=True, exist_ok=True)
    args.output.write_text(
        json.dumps(report, indent=2, sort_keys=True) + "\n",
        encoding="utf-8",
    )
    print(json.dumps(report, indent=2, sort_keys=True))
    if failures:
        raise SystemExit(2)


if __name__ == "__main__":
    main()
