"""proxym do — one-command workflow: describe → ticket → tool → run → logs."""

from __future__ import annotations

import sys
import time

import click

from proxym.cli._client import make_client
from proxym.cli.smart_defaults import (
    default_priority,
    detect_ticket_type,
    resolve_project,
    resolve_tool,
)


def _fetch_projects(client) -> list[dict]:
    """Get project list from API, tolerating errors."""
    try:
        r = client.get("/dashboard/projects")
        data = r.json()
        return data if isinstance(data, list) else data.get("projects", [])
    except Exception:
        return []


@click.command("do")
@click.argument("task", required=False)
@click.option("--on", "project_name", default=None, help="Project name or id")
@click.option("--with", "tool_name", default=None, help="Tool to use (aider, claude-code, …)")
@click.option("--priority", "-p", default=None, help="Priority (critical/high/medium/low)")
@click.option("--type", "task_type", default=None, help="Task type (bug/feature/refactor/test/task)")
@click.option("--no-run", is_flag=True, help="Create ticket but don't dispatch")
@click.option("--no-wait", is_flag=True, help="Dispatch but don't follow output")
@click.option("--dry-run", is_flag=True, help="Show plan without executing")
@click.pass_context
def do_cmd(ctx, task, project_name, tool_name, priority, task_type, no_run, no_wait, dry_run):
    """One command to rule them all.

    \b
    Examples:
      proxym do "fix crash in /health endpoint"
      proxym do "refactor panel.jsx" --on proxym --with claude-code
      proxym do                          # interactive mode
    """
    obj = ctx.obj or {}
    client = make_client(obj.get("proxy"), obj.get("key"))

    # Interactive mode
    if not task:
        task = click.prompt("  What to do?")

    # Resolve smart defaults
    projects = _fetch_projects(client)
    project = resolve_project(projects, explicit=project_name)
    if not task_type:
        task_type = detect_ticket_type(task)
    tool = resolve_tool(task_type, project, tool_name)
    if not priority:
        priority = default_priority(task_type)

    # Show plan
    proj_display = project["name"] if project else "(none)"
    click.echo(f"\n  📋 Task:     {task}")
    click.echo(f"  📁 Project:  {proj_display}")
    click.echo(f"  🔧 Tool:     {tool}")
    click.echo(f"  📌 Type:     {task_type}")
    click.echo(f"  ⚡ Priority: {priority}")

    if dry_run:
        click.echo("\n  [dry-run] Would create ticket and dispatch.")
        return

    # 1. Create ticket
    payload: dict = {
        "task": task,
        "type": task_type,
        "priority": priority,
        "tool": tool,
    }
    if project:
        payload["project_id"] = project.get("id", "")

    try:
        r = client.post("/dashboard/tickets", json=payload)
        r.raise_for_status()
    except Exception as exc:
        click.echo(f"\n  ❌ Failed to create ticket: {exc}")
        return

    ticket = r.json()
    ticket_id = ticket.get("id", "?")
    click.echo(f"\n  ✅ Ticket {ticket_id} created")

    if no_run:
        click.echo("  [--no-run] Ticket created, not dispatched.")
        return

    # 2. Dispatch
    try:
        r2 = client.post("/dashboard/tools/dispatch", json={
            "ticket_id": ticket_id,
            "tool": tool,
        })
        if r2.status_code >= 400:
            click.echo(f"  ⚠️  Dispatch failed ({r2.status_code}): {r2.text[:200]}")
            click.echo(f"  Ticket {ticket_id} created but not dispatched.")
            return
    except Exception as exc:
        click.echo(f"  ⚠️  Dispatch error: {exc}")
        return

    job_data = r2.json()
    job_id = job_data.get("job", {}).get("id") or job_data.get("job_id", "?")
    click.echo(f"  🚀 Dispatched → {tool} (job {job_id})")

    if no_wait:
        click.echo(f"\n  [--no-wait] Job {job_id} queued.")
        click.echo(f"  Check: proxym tools job {job_id}")
        return

    # 3. Follow output
    click.echo(f"\n  {'─' * 50}")
    click.echo("  Waiting for output… (Ctrl+C to detach)\n")

    try:
        for tick in range(120):  # max ~10 min polling at 5s
            time.sleep(5)
            try:
                r3 = client.get(f"/dashboard/tools/queue/jobs/{job_id}")
            except Exception:
                break
            if r3.status_code != 200:
                break
            j = r3.json()
            status = j.get("status", "unknown")

            if status == "done":
                result = j.get("result") or {}
                output = result.get("stdout", "")[-500:]
                files = result.get("files_changed", [])
                dur = j.get("duration_s", 0)
                click.echo(f"\n  ✅ Done in {dur:.0f}s")
                if files:
                    click.echo(f"  Files: {', '.join(files[:10])}")
                if output:
                    click.echo(f"\n{output}")
                return

            if status == "failed":
                error = j.get("error") or j.get("result", {}).get("stderr", "")
                click.echo(f"\n  ❌ Failed: {error[:300]}")
                return

            # Still running — spinner
            sys.stdout.write(f"\r  ⏳ {status}… ({tick * 5}s)")
            sys.stdout.flush()

    except KeyboardInterrupt:
        click.echo(f"\n\n  Detached. Job {job_id} still running.")
        click.echo(f"  Check: proxym tools job {job_id}")
