"""Baseline generation commands.

maeris baseline generate   Discover pages, generate stable tests, push to Maeris.
"""

from __future__ import annotations

import asyncio
import json
import os
import sys
from pathlib import Path

import click

from ._core import baseline_group
from ._utils import _repo_config_dir


# ---------------------------------------------------------------------------
# Auth helper (same pattern as repair_cmds.py)
# ---------------------------------------------------------------------------


def _auth_check(config_dir: Path) -> None:
    from maeris_mcp.auth.token_store import TokenStore

    ts = TokenStore(config_dir=config_dir)
    if not ts.is_authenticated():
        click.secho("✗ Not authenticated. Run 'maeris auth login' first.", fg="red")
        sys.exit(1)
    if ts.is_token_expired():
        click.secho("✗ Token expired. Run 'maeris auth login' to re-authenticate.", fg="red")
        sys.exit(1)


# ---------------------------------------------------------------------------
# Progress rendering
# ---------------------------------------------------------------------------


def _make_progress_callback(verbose: bool):
    """Return a callback that prints pipeline stage updates."""

    def _cb(stage: str, detail: str = "") -> None:
        if stage == "discover":
            click.echo(f"\n→ {detail}")
        elif stage == "discover_done":
            click.secho(f"  {detail}", fg="cyan")
        elif stage == "generate":
            click.echo(f"\n→ {detail}")
        elif stage == "generate_page":
            if verbose:
                click.echo(detail)
        elif stage == "generate_done":
            click.secho(f"  {detail}", fg="cyan")
        elif stage == "scripts":
            click.echo(f"\n→ {detail}")
        elif stage == "validate":
            click.echo(f"\n→ {detail}")
        elif stage == "run":
            click.echo(detail)
        elif stage == "repair":
            click.echo(f"\n→ {detail}")
        elif stage == "repair_ok":
            click.secho(detail, fg="yellow")
        elif stage == "repair_fail":
            click.secho(detail, fg="red")
        elif stage == "summary":
            click.echo(f"\n  {detail}")
        elif stage == "push":
            click.echo(f"\n→ {detail}")
        elif stage == "push_done":
            click.secho(f"  {detail}", fg="green")
        elif stage == "push_error":
            click.secho(f"  {detail}", fg="red")
        elif stage == "push_skip":
            click.secho(f"  {detail}", fg="yellow")
        elif stage == "dry_run":
            click.secho(f"  {detail}", fg="yellow")

    return _cb


# ---------------------------------------------------------------------------
# Command
# ---------------------------------------------------------------------------


@baseline_group.command("generate")
@click.option(
    "--source", "-s",
    required=True,
    help="Path to the frontend source root to scan.",
)
@click.option(
    "--url", "-u",
    default=None,
    help="Application base URL (auto-detected from Maeris app if omitted).",
)
@click.option(
    "--model", "-m",
    default="claude-sonnet-4-6",
    show_default=True,
    help="AI model to use for generation and repair.",
)
@click.option(
    "--browser", "-b",
    default="chromium",
    show_default=True,
    help="Playwright browser engine (chromium, firefox, webkit).",
)
@click.option(
    "--folder",
    default="Baseline",
    show_default=True,
    help="Maeris folder name for pushed tests.",
)
@click.option(
    "--dry-run",
    is_flag=True,
    help="Generate and validate tests but do NOT push to Maeris.",
)
@click.option(
    "--json", "output_json",
    is_flag=True,
    help="Output final result as JSON.",
)
@click.option(
    "--verbose", "-v",
    is_flag=True,
    help="Print per-page generation details.",
)
def baseline_generate(
    source: str,
    url: str | None,
    model: str,
    browser: str,
    folder: str,
    dry_run: bool,
    output_json: bool,
    verbose: bool,
) -> None:
    """Discover pages, generate stable tests, validate, and push to Maeris.

    \b
    Pipeline:
      1. Scan --source for pages and nav links (deterministic)
      2. Ask AI to generate test steps per page
      3. Run each test locally via Playwright (3 consecutive passes required)
      4. Attempt 1 repair for failing tests, then re-validate
      5. Push stable tests to Maeris (skipped with --dry-run)

    \b
    Example:
      maeris baseline generate --source ./frontend --url https://light-dev.up.railway.app
      maeris baseline generate --source ./frontend --dry-run
    """
    config_dir = _repo_config_dir()
    _auth_check(config_dir)

    scan_root = Path(source).expanduser().resolve()
    if not scan_root.exists():
        click.secho(f"✗ Source path does not exist: {scan_root}", fg="red")
        sys.exit(1)

    # Resolve base URL
    base_url = url
    if not base_url:
        # Try to auto-detect from Maeris app settings
        async def _detect_url() -> str | None:
            from maeris_mcp.maeris.client import MaerisClient
            os.environ["MAERIS_CONFIG_DIR"] = str(config_dir)
            try:
                async with MaerisClient() as client:
                    app = await client.get_current_app()
                    return (
                        app.get("app_url")
                        or app.get("base_url")
                        or app.get("url")
                    ) if app else None
            except Exception:
                return None

        try:
            with _spinner("Detecting base URL…"):

                base_url = asyncio.run(_detect_url())
        except Exception:
            base_url = None

    if not base_url:
        click.secho(
            "✗ Could not determine base URL. "
            "Pass --url https://light-dev.up.railway.app or set it in your Maeris app.",
            fg="red",
        )
        sys.exit(1)

    # Verify playwright is installed
    import subprocess
    py_exec = sys.executable
    check = subprocess.run([py_exec, "-c", "import playwright"], capture_output=True)
    if check.returncode != 0:
        click.secho(
            "✗ Playwright is not installed.\n"
            "  pip install playwright && python -m playwright install chromium",
            fg="red",
        )
        sys.exit(1)

    click.echo(f"\nMaeris Baseline Generator")
    click.echo(f"  source : {scan_root}")
    click.echo(f"  url    : {base_url}")
    click.echo(f"  model  : {model}")
    click.echo(f"  browser: {browser}")
    if dry_run:
        click.secho("  mode   : dry-run (no push)", fg="yellow")

    progress_cb = None if output_json else _make_progress_callback(verbose)

    async def _run():
        from maeris_mcp.maeris.client import MaerisClient
        from maeris_mcp.baseline import generate_baseline

        os.environ["MAERIS_CONFIG_DIR"] = str(config_dir)
        async with MaerisClient() as client:
            return await generate_baseline(
                client=client,
                scan_root=scan_root,
                base_url=base_url,
                model=model,
                dry_run=dry_run,
                browser=browser,
                folder_name=folder,
                progress_callback=progress_cb,
            )

    # Do NOT wrap in _spinner() here — the progress_callback emits stage updates
    # incrementally and a spinner context would suppress that output.
    if not output_json:
        click.echo("\nStarting baseline pipeline…")
    try:
        result = asyncio.run(_run())
    except Exception as exc:
        click.secho(f"\n✗ Baseline generation failed: {exc}", fg="red")
        sys.exit(1)

    # ------------------------------------------------------------------
    # Output
    # ------------------------------------------------------------------
    if output_json:
        out = {
            "discovered_journeys": len(
                [t for t in result.tests]
            ),
            "generated_tests": result.total,
            "stable_tests": result.pushed,
            "discarded_tests": result.unstable,
            "skipped_tests": result.skipped,
            "tests": result.to_dict()["tests"],
        }
        click.echo(json.dumps(out, indent=2))
    else:
        click.echo("")
        if result.pushed:
            click.secho(f"✓ {result.pushed} stable test(s) pushed to Maeris", fg="green")
        if result.unstable:
            click.secho(f"✗ {result.unstable} test(s) discarded (unstable)", fg="red")
        if result.skipped:
            click.secho(f"  {result.skipped} test(s) skipped (empty steps)", fg="yellow")
        if not result.total:
            click.secho(
                "  No tests generated — check that --source contains frontend source files.",
                fg="yellow",
            )

    # Exit 1 if any tests were unstable (useful for CI)
    if result.unstable and not dry_run:
        sys.exit(1)
