"""Typer-powered CLI entry point for lr-qrm."""

from __future__ import annotations

import json
from pathlib import Path

import typer

from . import __version__
from .box_commands import box_app
from .query_commands import query_app
from .client import QrmClient, QrmClientError, LoginState
from .commands_shared import (
    DEFAULT_BASE_URL,
    OutputFormat,
    emit,
    load_state_or_exit,
    resolve_config_path,
)
from .llm_cmd import _copy_skill, _get_version, _SKILL_NAME, _skill_source_dir
from .uut_commands import uut_app

app = typer.Typer(help="Interact with the Qestit QRM service.")
app.add_typer(uut_app, name="uut")
app.add_typer(box_app, name="box")
app.add_typer(query_app, name="query")


@app.callback(invoke_without_command=True)
def main(
    ctx: typer.Context,
    version: bool = typer.Option(
        False,
        "--version",
        help="Display the lr-qrm version and exit.",
        rich_help_panel="Global Options",
    ),
    install_skill: bool = typer.Option(
        False,
        "--install-skill",
        help="Install the bundled LLM skill to ~/.claude/skills/ and exit.",
    ),
    show_skill: bool = typer.Option(
        False,
        "--show-skill",
        help="Print the bundled SKILL.md to stdout and exit.",
    ),
) -> None:
    """Top-level callback showing help or version when requested."""

    if version:
        typer.echo(__version__)
        raise typer.Exit()

    if install_skill and show_skill:
        typer.secho(
            "--install-skill and --show-skill are mutually exclusive.",
            fg=typer.colors.RED,
            err=True,
        )
        raise typer.Exit(2)

    if show_skill:
        skill_md = _skill_source_dir() / "SKILL.md"
        typer.echo(skill_md.read_text(encoding="utf-8"))
        raise typer.Exit()

    if install_skill:
        # Claude Code
        claude_dest = Path.home() / ".claude" / "skills"
        existing = claude_dest / _SKILL_NAME
        if existing.exists():
            typer.secho(
                f"Replacing existing skill at {existing}/",
                fg=typer.colors.YELLOW,
                err=True,
            )
        claude_dest.mkdir(parents=True, exist_ok=True)
        result = _copy_skill(claude_dest)
        typer.secho(f"Claude Code: skill installed to {result}/", fg=typer.colors.GREEN)

        # GitHub Copilot — instructions file
        copilot_dest = Path.cwd() / ".github" / "instructions"
        copilot_file = copilot_dest / f"{_SKILL_NAME}.instructions.md"
        copilot_dest.mkdir(parents=True, exist_ok=True)
        skill_md = _skill_source_dir() / "SKILL.md"
        copilot_file.write_text(skill_md.read_text(encoding="utf-8"), encoding="utf-8")
        typer.secho(
            f"GitHub Copilot: instructions written to {copilot_file}",
            fg=typer.colors.GREEN,
        )

        # GitHub Copilot — enable useInstructionFiles in .vscode/settings.json
        vscode_dir = Path.cwd() / ".vscode"
        vscode_settings = vscode_dir / "settings.json"
        vscode_dir.mkdir(parents=True, exist_ok=True)
        try:
            vscode_data = (
                json.loads(vscode_settings.read_text(encoding="utf-8"))
                if vscode_settings.exists()
                else {}
            )
        except json.JSONDecodeError:
            vscode_data = {}
        _COPILOT_KEY = "github.copilot.chat.codeGeneration.useInstructionFiles"
        if not vscode_data.get(_COPILOT_KEY):
            vscode_data[_COPILOT_KEY] = True
            vscode_settings.write_text(json.dumps(vscode_data, indent=2) + "\n", encoding="utf-8")
            typer.secho(
                f"GitHub Copilot: enabled {_COPILOT_KEY} in {vscode_settings}",
                fg=typer.colors.GREEN,
            )
        else:
            typer.secho(
                f"GitHub Copilot: {_COPILOT_KEY} already enabled",
                fg=typer.colors.BRIGHT_BLACK,
            )

        typer.secho(f"Version: {_get_version()}", fg=typer.colors.BRIGHT_BLACK)
        raise typer.Exit()

    if ctx.invoked_subcommand is None:
        typer.echo(ctx.get_help())
        raise typer.Exit()


@app.command()
def status(
    config_path: Path = typer.Option(
        None,
        "--config-path",
        help="Override the location of the login.json file.",
    ),
    base_url: str = typer.Option(
        None,
        "--base-url",
        help="Override the base URL stored in the config (useful for testing).",
    ),
    insecure: bool = typer.Option(
        True,
        "--insecure",
        help="Disable TLS verification when contacting QRM.",
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.rich,
        "--output",
        "-o",
        case_sensitive=False,
        help="Choose output format: rich (default) or json.",
    ),
) -> None:
    """Check QRM health via the `/Result/Status` endpoint."""

    state = load_state_or_exit(config_path)

    client = QrmClient(
        base_url=base_url or str(state.base_url),
        verify_tls=not insecure and state.verify_tls,
    )

    try:
        payload = client.status(token=state.token)
    except QrmClientError as exc:
        typer.secho(f"Status check failed: {exc}", fg=typer.colors.RED)
        raise typer.Exit(code=1) from exc

    emit(payload, output)


@app.command()
def login(
    username: str = typer.Option(
        ..., "--username", "-u", prompt=True, help="QRM username.", envvar="QRM_USERNAME"
    ),
    password: str = typer.Option(
        ...,
        "--password",
        "-p",
        prompt=True,
        hide_input=True,
        help="QRM password.",
        envvar="QRM_PASSWORD",
    ),
    base_url: str = typer.Option(
        DEFAULT_BASE_URL,
        "--base-url",
        "-b",
        help="Base URL for the QRM API.",
    ),
    config_path: Path = typer.Option(
        None,
        "--config-path",
        help="Override the location of the login.json file.",
    ),
    insecure: bool = typer.Option(
        False,
        "--insecure",
        help="Disable TLS verification when contacting QRM.",
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.rich,
        "--output",
        "-o",
        case_sensitive=False,
        help="Choose output format: rich (default) or json.",
    ),
) -> None:
    """Authenticate against QRM and store the bearer token locally."""

    destination = resolve_config_path(config_path)
    destination.parent.mkdir(parents=True, exist_ok=True)

    client = QrmClient(base_url=base_url, verify_tls=not insecure)
    try:
        token = client.login(username=username, password=password)
    except QrmClientError as exc:
        typer.secho(f"Login failed: {exc}", fg=typer.colors.RED)
        raise typer.Exit(code=1) from exc

    state = LoginState(
        token=token,
        username=username,
        base_url=base_url,
        verify_tls=not insecure,
    )
    destination.write_text(state.model_dump_json(indent=2), encoding="utf-8")

    message = f"[green]Stored login token for {username} at {destination}[/green]"
    payload = {
        "username": username,
        "config_path": str(destination),
    }
    emit(payload if output is OutputFormat.json else message, output)


__all__ = ["app"]
