from __future__ import annotations

import json
from pathlib import Path

from app.config import Settings

_ACCURATE_MODELS = {"medium", "large", "large-v2", "large-v3"}


def ensure_gates_file(settings: Settings) -> None:
    path = settings.gates_path
    if path.exists():
        return
    example = settings.root / "config" / "launch-gates.example.json"
    path.parent.mkdir(parents=True, exist_ok=True)
    if example.exists():
        path.write_text(example.read_text(encoding="utf-8"), encoding="utf-8")
    else:
        path.write_text("{}\n", encoding="utf-8")


def load_gates(path: Path) -> dict:
    if not path.exists():
        return {}
    try:
        data = json.loads(path.read_text(encoding="utf-8"))
    except json.JSONDecodeError:
        return {}
    return data if isinstance(data, dict) else {}


def evaluate_gates(data: dict, settings: Settings) -> list[str]:
    notes = data.get("notes") if isinstance(data.get("notes"), dict) else {}
    problems: list[str] = []
    if not data:
        problems.append("The launch file is missing or unreadable.")
        return problems

    if not data.get("eligible_video_policy_confirmed"):
        problems.append(
            "Confirm which videos may be downloaded, and that the rights checkbox is the policy you want."
        )
    if not data.get("max_duration_confirmed"):
        problems.append(
            f"Confirm the maximum video length. The desk is set to {settings.max_duration_seconds} seconds. "
            "Write that number into the launch file."
        )
    elif notes.get("max_duration_seconds") != settings.max_duration_seconds:
        problems.append(
            "The confirmed maximum length does not match VAANI_MAX_DURATION_SECONDS."
        )

    if not data.get("retention_confirmed"):
        problems.append(
            f"Confirm how long files stay. The desk deletes them after {settings.retention_hours} hours."
        )
    elif notes.get("retention_hours") != settings.retention_hours:
        problems.append("The confirmed retention does not match VAANI_RETENTION_HOURS.")

    if not data.get("hindi_accuracy_confirmed"):
        problems.append(
            f"Run a Hindi test set and record a character error rate at or below {settings.hindi_cer_max} "
            "on the medium or large-v3 model."
        )
    else:
        cer = notes.get("hindi_cer")
        model = notes.get("whisper_model")
        if isinstance(cer, bool) or not isinstance(cer, (int, float)):
            problems.append("Hindi accuracy is marked confirmed, but hindi_cer is missing.")
        elif float(cer) > settings.hindi_cer_max:
            problems.append(
                f"The Hindi character error rate {cer} is above the limit of {settings.hindi_cer_max}."
            )
        if not isinstance(model, str) or not model.strip():
            problems.append("Hindi accuracy notes need the speech model name.")
        elif model.strip() not in _ACCURATE_MODELS:
            problems.append("Hindi accuracy must be measured on medium or large-v3.")
        if settings.whisper_model not in _ACCURATE_MODELS:
            problems.append(
                f"The running speech model is {settings.whisper_model}. Production needs medium or large-v3."
            )

    if not data.get("audio_fallback_confirmed"):
        problems.append(
            "Confirm the upload fallback for videos whose audio YouTube will not release."
        )
    return problems


def gate_status(settings: Settings) -> dict:
    ensure_gates_file(settings)
    data = load_gates(settings.gates_path)
    problems = evaluate_gates(data, settings)
    return {"ok": not problems, "problems": problems}
