"""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,
)


# ── helpers (each CC ≤ 6) ────────────────────────────────────


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 []


def _resolve_all(client, task, project_name, tool_name, task_type, priority):
    """Resolve project, type, tool, priority from smart defaults."""
    projects = _fetch_projects(client)
    project = resolve_project(projects, explicit=project_name)
    task_type = task_type or detect_ticket_type(task)
    tool = resolve_tool(task_type, project, tool_name)
    priority = priority or default_priority(task_type)
    return project, task_type, tool, priority


def _print_plan(task, project, tool, task_type, priority):
    """Display resolved 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}")


def _create_ticket(client, task, project, tool, task_type, priority):
    """Create ticket via API. Returns (ticket_id, ok)."""
    payload = {"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()
        ticket_id = r.json().get("id", "?")
        click.echo(f"\n  Ticket {ticket_id} created")
        return ticket_id, True
    except Exception as exc:
        click.echo(f"\n  Failed to create ticket: {exc}")
        return None, False


def _dispatch(client, ticket_id, tool):
    """Dispatch tool for ticket. Returns job_id or None."""
    try:
        r = client.post("/dashboard/tools/dispatch", json={
            "ticket_id": ticket_id, "tool": tool,
        })
        if r.status_code >= 400:
            click.echo(f"  Dispatch failed ({r.status_code}): {r.text[:200]}")
            return None
        data = r.json()
        job_id = data.get("job", {}).get("id") or data.get("job_id", "?")
        click.echo(f"  Dispatched -> {tool} (job {job_id})")
        return job_id
    except Exception as exc:
        click.echo(f"  Dispatch error: {exc}")
        return None


def _print_done(job):
    """Print completion summary."""
    result = job.get("result") or {}
    dur = job.get("duration_s", 0)
    click.echo(f"\n  Done in {dur:.0f}s")
    files = result.get("files_changed", [])
    if files:
        click.echo(f"  Files: {', '.join(files[:10])}")
    output = result.get("stdout", "")[-500:]
    if output:
        click.echo(f"\n{output}")


def _follow_job(client, job_id, poll_interval=5, max_polls=120):
    """Poll job status until done/failed. Ctrl+C detaches."""
    click.echo(f"\n  {'─' * 50}")
    click.echo("  Waiting for output... (Ctrl+C to detach)\n")
    try:
        for tick in range(max_polls):
            time.sleep(poll_interval)
            try:
                r = client.get(f"/dashboard/tools/queue/jobs/{job_id}")
            except Exception:
                break
            if r.status_code != 200:
                break
            job = r.json()
            status = job.get("status", "unknown")
            if status == "done":
                _print_done(job)
                return
            if status == "failed":
                err = job.get("error") or job.get("result", {}).get("stderr", "")
                click.echo(f"\n  Failed: {err[:300]}")
                return
            sys.stdout.write(f"\r  {status}... ({tick * poll_interval}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}")


# ── CLI command ──────────────────────────────────────────────


@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"))

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

    project, task_type, tool, priority = _resolve_all(
        client, task, project_name, tool_name, task_type, priority,
    )
    _print_plan(task, project, tool, task_type, priority)

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

    ticket_id, ok = _create_ticket(client, task, project, tool, task_type, priority)
    if not ok:
        return

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

    job_id = _dispatch(client, ticket_id, tool)
    if not job_id:
        return

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

    _follow_job(client, job_id)
