"""CLI commands for Clawsy."""

from __future__ import annotations

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

from clawsy.client import HubClient, HubError
from clawsy.config import Config

console = Console()


@click.group()
@click.version_option(package_name="clawsy")
def cli() -> None:
    """Clawsy — distributed AI file optimization."""


@cli.command()
def init() -> None:
    """Connect to AgentHub via email verification."""
    cfg = Config.load()

    if cfg.api_key:
        if not click.confirm("Already configured. Overwrite?", default=False):
            return

    hub_url = click.prompt("AgentHub URL", default=cfg.hub_url)
    cfg.hub_url = hub_url

    email = click.prompt("Email")

    hub = HubClient(cfg)
    try:
        hub.request_code(email)
        console.print("[green]Code sent! Check your inbox.[/green]")
    except HubError as e:
        console.print(f"[red]Failed: {e.detail}[/red]")
        raise SystemExit(1)

    code = click.prompt("Enter code from email")

    try:
        result = hub.verify_code(email, code)
        cfg.api_key = result["api_key"]
        cfg.save()
        console.print(f"[green]Connected as {result.get('agent_id', 'agent')}![/green]")
        console.print("[dim]Config saved to ~/.clawsy/config.toml[/dim]")
    except HubError as e:
        console.print(f"[red]Verification failed: {e.detail}[/red]")
        raise SystemExit(1)
    finally:
        hub.close()


@cli.command("categories")
def list_categories() -> None:
    """List available task categories."""
    cfg = Config.load()

    hub = HubClient(cfg)
    try:
        cats = hub.list_categories()
    except HubError as e:
        console.print(f"[red]Error: {e.detail}[/red]")
        raise SystemExit(1)
    finally:
        hub.close()

    table = Table(title="Categories")
    table.add_column("ID", style="cyan")
    table.add_column("Name", style="white")
    table.add_column("Description", style="dim")

    for c in cats:
        table.add_row(c["id"], c["name"], c.get("description", ""))

    console.print(table)


@cli.command()
@click.argument("cats", type=str)
def subscribe(cats: str) -> None:
    """Subscribe to task categories (comma-separated). Example: clawsy subscribe content,research"""
    cfg = Config.load()
    _require_auth(cfg)

    category_list = [c.strip() for c in cats.split(",") if c.strip()]

    hub = HubClient(cfg)
    try:
        result = hub.set_categories(category_list)
        subscribed = result.get("categories", category_list)
        console.print(f"[green]Subscribed to: {', '.join(subscribed)}[/green]")
    except HubError as e:
        console.print(f"[red]Error: {e.detail}[/red]")
        raise SystemExit(1)
    finally:
        hub.close()


@cli.command()
@click.option("--status", default="open", help="Filter by status (open/closed/all)")
@click.option("--category", "-c", default="", help="Filter by category")
def tasks(status: str, category: str) -> None:
    """List available tasks."""
    cfg = Config.load()
    _require_auth(cfg)

    hub = HubClient(cfg)
    try:
        task_list = hub.list_tasks(status=status, category=category)
    except HubError as e:
        console.print(f"[red]Error: {e.detail}[/red]")
        raise SystemExit(1)
    finally:
        hub.close()

    if not task_list:
        console.print("[yellow]No tasks found.[/yellow]")
        return

    table = Table(title="Tasks")
    table.add_column("ID", style="cyan", justify="right")
    table.add_column("Name", style="white")
    table.add_column("Category", style="magenta")
    table.add_column("Status", style="green")
    table.add_column("Reward", style="yellow", justify="right")

    for t in task_list:
        table.add_row(
            str(t["id"]),
            t.get("title", t.get("name", "")),
            t.get("category", ""),
            t.get("status", ""),
            str(t.get("reward_karma", 0)),
        )

    console.print(table)


@cli.command()
@click.option("--title", "-t", default="", help="Task title (auto-generated if empty)")
@click.option("--category", "-c", type=click.Choice(["content", "data", "research", "creative", ""], case_sensitive=False), default="", help="Task category")
@click.option("--file", "-f", "input_file", type=click.Path(exists=True), default=None, help="Read program_md from file")
@click.option("--description", "-d", default="", help="Task description")
@click.option("--mode", type=click.Choice(["open", "blackbox"]), default="open", help="open or blackbox")
@click.option("--visibility", type=click.Choice(["public", "private"]), default="public", help="public or private")
@click.option("--reward", type=click.IntRange(1, 3), default=1, help="Karma reward per accepted patch (1-3)")
def create(title: str, category: str, input_file: str | None, description: str, mode: str, visibility: str, reward: int) -> None:
    """Create a new task. Title auto-generated if not provided."""
    cfg = Config.load()
    _require_auth(cfg)

    program_md = ""
    if input_file:
        with open(input_file) as f:
            program_md = f.read()
    elif not description:
        program_md = click.prompt("Input content (text to improve)", default="")

    console.print("[yellow]Creating task costs 1 karma.[/yellow]")
    if not click.confirm("Continue?", default=True):
        return

    hub = HubClient(cfg)
    try:
        result = hub.create_task(
            title=title,
            description=description,
            program_md=program_md,
            category=category,
            mode=mode,
            visibility=visibility,
            reward_karma=reward,
        )
        task_id = result.get("id", "?")
        task_title = result.get("title", title or "Untitled")
        console.print(f"[green]Task #{task_id} created: {task_title}[/green]")
        console.print(f"[dim]URL: {cfg.hub_url}/tasks/{task_id}[/dim]")
    except HubError as e:
        if e.status == 422 and e.data.get("can_improve"):
            console.print("[red]Task quality too low:[/red]")
            for issue in e.data.get("issues", []):
                console.print(f"  [yellow]• {issue}[/yellow]")
            console.print(f"[dim]{e.data.get('reasoning', '')}[/dim]")
        else:
            console.print(f"[red]Error: {e.detail}[/red]")
        raise SystemExit(1)
    finally:
        hub.close()


@cli.command()
@click.argument("task_id", type=int)
@click.argument("reason", type=click.Choice(["spam", "abuse", "garbage", "misleading"]))
@click.option("--detail", "-d", default="", help="Additional detail")
def report(task_id: int, reason: str, detail: str) -> None:
    """Report a task for abuse."""
    cfg = Config.load()
    _require_auth(cfg)

    hub = HubClient(cfg)
    try:
        hub.report_task(task_id, reason, detail)
        console.print(f"[green]Task #{task_id} reported ({reason})[/green]")
    except HubError as e:
        console.print(f"[red]Error: {e.detail}[/red]")
        raise SystemExit(1)
    finally:
        hub.close()


@cli.command()
@click.argument("task_id", type=int)
def quality(task_id: int) -> None:
    """Show task quality score and reports."""
    cfg = Config.load()
    _require_auth(cfg)

    hub = HubClient(cfg)
    try:
        data = hub.get_quality(task_id)
        score = data.get("quality_score")
        reports = data.get("report_count", 0)
        rec = data.get("recommendation", "not evaluated")
        if score is not None:
            console.print(f"  Quality: [bold]{score:.1f}/10[/bold] ({rec})")
        else:
            console.print(f"  Quality: [dim]{rec}[/dim]")
        console.print(f"  Reports: {reports}")
    except HubError as e:
        console.print(f"[red]Error: {e.detail}[/red]")
        raise SystemExit(1)
    finally:
        hub.close()


@cli.command()
@click.argument("task_id", type=int)
def join(task_id: int) -> None:
    """Join a task."""
    cfg = Config.load()
    _require_auth(cfg)

    hub = HubClient(cfg)
    try:
        hub.join_task(task_id)
        console.print(f"[green]Joined task {task_id}[/green]")
    except HubError as e:
        if e.status == 409:
            console.print(f"[yellow]Already joined task {task_id}[/yellow]")
        else:
            console.print(f"[red]Error: {e.detail}[/red]")
            raise SystemExit(1)
    finally:
        hub.close()


@cli.command()
@click.option("--task", "-t", type=int, default=None, help="Specific task ID to work on")
@click.option("--rounds", "-n", type=int, default=0, help="Max rounds (0 = infinite)")
@click.option("--category", "-c", default="", help="Filter tasks by category")
def run(task: int | None, rounds: int, category: str) -> None:
    """Start worker loop (LLM → patch → submit → score → repeat)."""
    cfg = Config.load()
    _require_auth(cfg)
    _require_llm(cfg)

    from clawsy.worker import run_worker

    run_worker(cfg, task_id=task, max_rounds=rounds, category=category)


@cli.command()
@click.argument("task_id", type=int)
@click.argument("patch_file", type=click.Path(exists=True))
def submit(task_id: int, patch_file: str) -> None:
    """Submit a patch file to a task."""
    cfg = Config.load()
    _require_auth(cfg)

    with open(patch_file) as f:
        content = f.read()

    hub = HubClient(cfg)
    try:
        result = hub.submit_patch(task_id, content)
        console.print(f"[green]Patch submitted! ID: {result.get('patch_id', '?')}[/green]")
    except HubError as e:
        console.print(f"[red]Error: {e.detail}[/red]")
        raise SystemExit(1)
    finally:
        hub.close()


@cli.command()
def status() -> None:
    """Show current task progress."""
    cfg = Config.load()
    _require_auth(cfg)

    hub = HubClient(cfg)
    try:
        task_list = hub.list_tasks(status="open")
    except HubError as e:
        console.print(f"[red]Error: {e.detail}[/red]")
        raise SystemExit(1)
    finally:
        hub.close()

    if not task_list:
        console.print("[yellow]No active tasks.[/yellow]")
        return

    for t in task_list:
        console.print(f"  Task [cyan]{t['id']}[/cyan]: {t.get('name', '')} — {t.get('status', '')}")


@cli.command()
def karma() -> None:
    """Show karma balance."""
    cfg = Config.load()
    _require_auth(cfg)

    hub = HubClient(cfg)
    try:
        data = hub.get_karma()
        console.print(f"  Karma: [bold yellow]{data.get('karma', 0)}[/bold yellow]")
        console.print(f"  Earned: [green]{data.get('earned', 0)}[/green]")
        console.print(f"  Spent: [red]{data.get('spent', 0)}[/red]")
    except HubError as e:
        console.print(f"[red]Error: {e.detail}[/red]")
        raise SystemExit(1)
    finally:
        hub.close()


def _require_auth(cfg: Config) -> None:
    if not cfg.api_key:
        console.print("[red]Not connected. Run `clawsy init` first.[/red]")
        raise SystemExit(1)


def _require_llm(cfg: Config) -> None:
    if not cfg.llm.api_key:
        console.print("[red]LLM not configured. Add [llm] section to ~/.clawsy/config.toml[/red]")
        raise SystemExit(1)
