"""Loony CLI — governed data services for agents."""

from typing import Optional

import typer
from rich.console import Console
from rich.table import Table

from . import __version__, api, auth, config
from .init import init_project
from . import skills as skills_mod

app = typer.Typer(
    name="loony",
    help="Governed data services for agents.",
    no_args_is_help=True,
)
console = Console()


@app.callback(invoke_without_command=True)
def main(
    version: bool = typer.Option(False, "--version", "-v", help="Show version"),
):
    if version:
        console.print(f"loony {__version__}")
        raise typer.Exit()


@app.command()
def init(
    name: str = typer.Argument(..., help="Service name"),
    agent: Optional[str] = typer.Option(None, "--agent", "-a", help="Agent type: claude, cursor, codex"),
    update: bool = typer.Option(False, "--update", "-u", help="Update loony templates only, preserve user files"),
):
    """Scaffold a new pipeline project, or update loony templates."""
    from pathlib import Path

    result = init_project(name, agent=agent, project_dir=Path.cwd(), update=update)

    if update:
        console.print(f"\n[green]✓[/green] Updated loony templates for [bold]{result['name']}[/bold]\n")
        if result["updated"]:
            console.print("[bold]Updated:[/bold]")
            for f in result["updated"]:
                console.print(f"  [yellow]{f}[/yellow]")
        else:
            console.print("[dim]Everything up to date.[/dim]")
    else:
        console.print(f"\n[green]✓[/green] Created service [bold]{result['name']}[/bold]\n")

        if result["created"]:
            console.print("[bold]Core files:[/bold]")
            for f in result["created"]:
                console.print(f"  {f}")

        if result["skipped"]:
            console.print(f"\n[dim]Skipped (already exist): {', '.join(result['skipped'])}[/dim]")

        console.print(f"\n[bold]Next steps:[/bold]")
        console.print("  1. Edit schema.yaml — define your tables, columns, sync modes")
        console.print("  2. Write scripts in scripts/ — dlt scripts that export run(conn)")
        console.print("  3. Write transforms in transforms/ — SQL to clean and aggregate")
        console.print("  4. Run [bold]loony test[/bold] to validate")
        console.print("  5. Run [bold]loony deploy[/bold] to go live")


@app.command()
def login(
    env: Optional[str] = typer.Option(None, "--env", "-e", help="Environment to login to"),
):
    """Authenticate with loony.dev via browser."""
    env = env or config.get_current_env()
    console.print(f"Logging into [bold]{env}[/bold]...")
    console.print("Opening browser...")

    try:
        user = auth.login(env)
        console.print(f"\n[green]✓[/green] Logged in as [bold]{user['email']}[/bold]")
        console.print(f"  User ID: {user['user_id']}")
        console.print(f"  Environment: {env}")
    except Exception as e:
        console.print(f"\n[red]✗[/red] Login failed: {e}")
        raise typer.Exit(1)


@app.command()
def logout(
    env: Optional[str] = typer.Option(None, "--env", "-e", help="Environment to logout from"),
):
    """Clear stored credentials."""
    env = env or config.get_current_env()
    config.clear_credentials(env)
    console.print(f"[green]✓[/green] Logged out from [bold]{env}[/bold]")


@app.command()
def env(
    name: Optional[str] = typer.Argument(None, help="Environment to switch to"),
):
    """Show or switch the current environment."""
    if name:
        config.set_current_env(name)
        console.print(f"[green]✓[/green] Switched to [bold]{name}[/bold]")
    else:
        current = config.get_current_env()
        cfg = config.load()
        envs = cfg.get("environments", {})

        table = Table(title="Environments")
        table.add_column("Name")
        table.add_column("Endpoint")
        table.add_column("User")
        table.add_column("Active")

        for env_name in set(config.DEFAULTS.keys()) | set(envs.keys()):
            env_config = config.get_env_config(env_name)
            endpoint = env_config.get("endpoint", "")
            email = env_config.get("email", "")
            active = "→" if env_name == current else ""
            table.add_row(env_name, endpoint or "(not configured)", email or "(not logged in)", active)

        console.print(table)


@app.command()
def status():
    """Check connection to control plane and show user info."""
    current = config.get_current_env()
    env_config = config.get_env_config()

    console.print(f"Environment: [bold]{current}[/bold]")
    console.print(f"Endpoint: {env_config.get('endpoint', '(not configured)')}")
    console.print()

    # Health check
    try:
        h = api.health()
        console.print(f"[green]✓[/green] Control plane: {h.get('status', 'unknown')}")
    except Exception as e:
        console.print(f"[red]✗[/red] Control plane: {e}")
        raise typer.Exit(1)

    # Auth check
    try:
        user = api.me()
        console.print(f"[green]✓[/green] Authenticated as: {user.get('email')}")
        console.print(f"  User ID: {user.get('user_id')}")
    except ValueError as e:
        console.print(f"[yellow]⚠[/yellow] {e}")
    except Exception as e:
        console.print(f"[red]✗[/red] Auth failed: {e}")


# ─── Feedback ──────────────────────────────────────────────────────────────────

@app.command()
def feedback(
    message: str = typer.Argument(..., help="Describe the issue or suggestion"),
    include_traceback: bool = typer.Option(True, "--traceback/--no-traceback", help="Include recent Python traceback if available"),
):
    """Submit feedback or report a bug. Creates a tracked issue with full context."""
    import platform
    import sys
    import traceback as tb_mod

    console.print("[dim]Gathering context...[/dim]")

    payload = {
        "message": message,
        "cli_version": __version__,
        "python_version": platform.python_version(),
        "os": f"{platform.system()} {platform.release()}",
        "environment": config.get_current_env(),
    }

    # Capture last traceback if available
    if include_traceback:
        last_tb = tb_mod.format_exc()
        if last_tb and last_tb.strip() != "NoneType: None":
            payload["traceback"] = last_tb

    try:
        result = api.submit_feedback(payload)
        console.print(f"\n[green]✓[/green] Feedback submitted")
        if result.get("issue_url"):
            console.print(f"  Tracking: {result['issue_url']}")
        if result.get("issue_number"):
            console.print(f"  Issue #{result['issue_number']}")
    except ValueError as e:
        console.print(f"[red]✗[/red] {e}")
        raise typer.Exit(1)
    except Exception as e:
        console.print(f"[red]✗[/red] Failed to submit feedback: {e}")
        raise typer.Exit(1)


# ─── Skills ────────────────────────────────────────────────────────────────────

skills_app = typer.Typer(help="Manage agent skills.")
app.add_typer(skills_app, name="skills")


@skills_app.callback(invoke_without_command=True)
def skills_default(ctx: typer.Context):
    """List available and installed skills."""
    if ctx.invoked_subcommand is not None:
        return
    # Default: show list
    _skills_list()


@skills_app.command("list")
def skills_list():
    """List available and installed skills."""
    _skills_list()


def _skills_list():
    from pathlib import Path

    result = skills_mod.list_skills(Path.cwd())

    table = Table(title="Skills")
    table.add_column("Name")
    table.add_column("Description")
    table.add_column("Status")

    for name, desc in result["available"].items():
        if name in result["installed"]:
            status = "[green]installed[/green]"
        else:
            status = "[dim]available[/dim]"
        table.add_row(name, desc, status)

    # Show user skills too
    for name, kind in result["installed"].items():
        if kind == "user":
            table.add_row(name, "(user-created)", "[cyan]custom[/cyan]")

    console.print(table)

    if not result["agent"]:
        console.print("\n[yellow]⚠[/yellow] No agent detected. Run 'loony init' first.")


@skills_app.command("add")
def skills_add(
    name: str = typer.Argument(..., help="Skill name to add"),
    agent: Optional[str] = typer.Option(None, "--agent", "-a", help="Agent type: claude, cursor, codex"),
):
    """Add a bundled skill to the project."""
    from pathlib import Path

    try:
        result = skills_mod.add_skill(name, agent=agent, project_dir=Path.cwd())
        console.print(f"[green]✓[/green] {result['action'].title()} skill [bold]{result['name']}[/bold]")
        console.print(f"  {result['path']}")
    except ValueError as e:
        console.print(f"[red]✗[/red] {e}")
        raise typer.Exit(1)


@skills_app.command("remove")
def skills_remove(
    name: str = typer.Argument(..., help="Skill name to remove"),
):
    """Remove a skill from the project."""
    from pathlib import Path

    try:
        result = skills_mod.remove_skill(name, project_dir=Path.cwd())
        console.print(f"[green]✓[/green] Removed skill [bold]{result['name']}[/bold]")
    except ValueError as e:
        console.print(f"[red]✗[/red] {e}")
        raise typer.Exit(1)


if __name__ == "__main__":
    app()
