"""``evalytic init`` command -- interactive setup wizard."""

from __future__ import annotations

import os
import sys
from pathlib import Path
from typing import Any

import click
from rich.console import Console
from rich.panel import Panel

console = Console()

_USE_CASES = {
    1: ("Compare text-to-image models (Flux, SDXL, Recraft...)", True, "text2img"),
    2: ("Compare image-editing models (Kontext, Seedream...)", True, "img2img"),
    3: ("Score existing images (no generation)", False, "eval"),
    4: ("CI/CD quality gate", False, "gate"),
}

_KEY_CONFIG = {
    "fal": {
        "env_var": "FAL_KEY",
        "label": "fal.ai API key",
        "url": "https://fal.ai/dashboard/keys",
        "prefix": "fal",
    },
    "gemini": {
        "env_var": "GEMINI_API_KEY",
        "label": "Google Gemini API key",
        "url": "https://aistudio.google.com/apikey",
        "prefix": "AI",
    },
}


def _mask_key(key: str) -> str:
    """Mask an API key: show first 4 + *** + last 4 chars."""
    if len(key) <= 8:
        return "***"
    return key[:4] + "***" + key[-4:]


def _validate_gemini_key(key: str) -> bool:
    """Validate Gemini key with a lightweight API call."""
    try:
        import httpx

        resp = httpx.get(
            f"https://generativelanguage.googleapis.com/v1beta/models?key={key}",
            timeout=10,
        )
        return resp.status_code == 200
    except Exception:
        return False


def _validate_fal_key(key: str) -> bool:
    """Basic validation: FAL keys should start with expected prefix."""
    return bool(key and len(key) > 10)


def _prompt_number(prompt: str, choices: range, default: int = 1) -> int:
    """Ask user to pick a number from a range."""
    while True:
        raw = input(prompt).strip()
        if not raw:
            return default
        try:
            val = int(raw)
            if val in choices:
                return val
        except ValueError:
            pass
        console.print(f"  [yellow]Please enter a number between {choices.start} and {choices.stop - 1}[/yellow]")


def _prompt_yn(prompt: str, default: bool = True) -> bool:
    """Ask a yes/no question."""
    hint = "[Y/n]" if default else "[y/N]"
    raw = input(f"{prompt} {hint} ").strip().lower()
    if not raw:
        return default
    return raw in ("y", "yes")


def _collect_key(key_id: str, required: bool = True) -> str | None:
    """Collect an API key, checking env first."""
    cfg = _KEY_CONFIG[key_id]
    env_val = os.environ.get(cfg["env_var"])

    if env_val:
        console.print(f"  {cfg['label']}: [green]{_mask_key(env_val)}[/green] (from environment, keeping)")
        return None  # Signal: already set, don't write to toml

    if not required:
        return None

    console.print(f"\n  {cfg['label']}")
    console.print(f"  Get one at: [blue]{cfg['url']}[/blue]")
    key = input(f"  Enter key: ").strip()

    if not key:
        console.print(f"  [yellow]Skipped.[/yellow] Set {cfg['env_var']} later.")
        return None

    # Validate
    validator = _validate_gemini_key if key_id == "gemini" else _validate_fal_key
    if validator(key):
        console.print(f"  [green]Valid![/green]")
    else:
        console.print(f"  [yellow]Warning: Could not validate key. Saving anyway.[/yellow]")

    return key


def _write_toml(path: Path, keys: dict[str, str], judge: str = "gemini-2.5-flash") -> None:
    """Write evalytic.toml config file."""
    lines = ["# evalytic.toml -- generated by `evalytic init`", ""]

    key_entries = {k: v for k, v in keys.items() if v}
    if key_entries:
        lines.append("[keys]")
        for k, v in key_entries.items():
            lines.append(f'{k} = "{v}"')
        lines.append("")

    lines.append("[bench]")
    lines.append(f'judge = "{judge}"')
    lines.append("")

    path.write_text("\n".join(lines))


def _run_demo(judge: str = "gemini-2.5-flash") -> None:
    """Run a quick demo benchmark."""
    from ..bench.runner import run_bench
    from ..report.terminal import print_full_report

    try:
        report = run_bench(
            models=["flux-schnell"],
            prompts=[{"prompt": "A cat in a top hat, watercolor style"}],
            dimensions=["visual_quality", "prompt_adherence"],
            judge=judge,
        )
        print_full_report(report)
    except Exception as exc:
        console.print(f"\n  [yellow]Demo failed: {exc}[/yellow]")
        console.print("  Don't worry — you can run benchmarks manually.\n")


@click.command("init")
@click.option("--force", is_flag=True, help="Overwrite existing evalytic.toml.")
@click.option("--skip-demo", is_flag=True, help="Skip the demo benchmark.")
def init_cmd(force: bool, skip_demo: bool) -> None:
    """Interactive setup wizard for Evalytic."""
    toml_path = Path("evalytic.toml")

    # Step 1: Welcome + existing config check
    console.print(Panel.fit(
        "[bold]Welcome to Evalytic![/bold]\n"
        "This wizard will set up your configuration.",
        border_style="blue",
    ))

    if toml_path.exists() and not force:
        console.print(f"  [yellow]Found existing {toml_path}[/yellow]")
        if not _prompt_yn("  Overwrite?", default=False):
            console.print("  Keeping existing config. Use --force to overwrite.")
            return

    # Step 2: Use case
    console.print("\n  [bold]What will you use Evalytic for?[/bold]")
    for num, (desc, _, _) in _USE_CASES.items():
        console.print(f"    {num}. {desc}")
    use_case = _prompt_number("  Enter number [1]: ", range(1, 5), default=1)

    _, needs_fal, uc_type = _USE_CASES[use_case]

    # Step 3: API keys
    console.print("\n  [bold]API Keys[/bold]")

    keys: dict[str, str] = {}
    judge = "gemini-2.5-flash"

    # FAL needed for generation use cases, also works as judge
    if needs_fal:
        fal_key = _collect_key("fal", required=True)
        if fal_key:
            keys["fal"] = fal_key
    else:
        fal_key = None

    has_fal_key = bool(fal_key or os.environ.get("FAL_KEY"))

    # Gemini is optional if FAL_KEY is available (fal/gemini-2.5-flash works as judge)
    if has_fal_key:
        console.print("\n  [dim]Your FAL_KEY can also handle judging (via fal/gemini-2.5-flash).[/dim]")
        if _prompt_yn("  Add a separate Gemini key? (optional, slightly cheaper)", default=False):
            gemini_key = _collect_key("gemini", required=True)
        else:
            gemini_key = None
            judge = "fal/gemini-2.5-flash"
    else:
        gemini_key = _collect_key("gemini", required=True)

    if gemini_key:
        keys["gemini"] = gemini_key

    # Step 4: Write toml
    _write_toml(toml_path, keys, judge=judge)
    console.print(f"\n  [green]Config written to {toml_path}[/green]")

    # Step 5: Demo benchmark
    has_fal = needs_fal and (fal_key or os.environ.get("FAL_KEY"))
    has_judge = gemini_key or os.environ.get("GEMINI_API_KEY") or has_fal_key

    if not skip_demo and has_fal and has_judge:
        if _prompt_yn("\n  Run a quick demo benchmark (~$0.003)?"):
            # Apply keys to env for demo
            if gemini_key:
                os.environ["GEMINI_API_KEY"] = gemini_key
            if fal_key:
                os.environ["FAL_KEY"] = fal_key
            console.print()
            _run_demo(judge=judge)

    # Step 6: Next steps
    console.print("\n  [bold]Next Steps[/bold]")
    if uc_type == "text2img":
        console.print("    evalytic bench -m flux-schnell -m flux-dev -p \"A cat\" -y")
        console.print("    evalytic bench -m flux-schnell --prompts prompts.json -y")
    elif uc_type == "img2img":
        console.print("    evalytic bench -m flux-kontext -i inputs.json -y")
    elif uc_type == "eval":
        console.print("    evalytic eval --image photo.jpg --prompt \"A sunset\"")
    elif uc_type == "gate":
        console.print("    evalytic gate --report results.json --threshold 3.5")

    console.print("\n    evalytic --help        Full command list")
    console.print("    https://docs.evalytic.ai   Documentation\n")
