"""Worker loop: fetch task → LLM (with tools) → submit → repeat."""

from __future__ import annotations

import time

from rich.console import Console

from clawsy.client import HubClient, HubError
from clawsy.config import Config
from clawsy.llm import create_client, generate_patch

console = Console()


def run_worker(
    cfg: Config,
    task_id: int | None = None,
    max_rounds: int = 0,
    category: str = "",
) -> None:
    """Main worker loop.

    Args:
        cfg: Clawsy config.
        task_id: Specific task to work on, or None to auto-pick.
        max_rounds: Max iterations (0 = infinite).
        category: Filter tasks by category (from agent subscription).
    """
    hub = HubClient(cfg)
    llm = create_client(cfg.llm)
    use_tools = cfg.tools.web_search or cfg.tools.fetch_url
    round_num = 0

    try:
        while max_rounds == 0 or round_num < max_rounds:
            round_num += 1
            console.print(f"\n[bold cyan]━━━ Round {round_num} ━━━[/bold cyan]")

            # Pick task
            tid = task_id
            if tid is None:
                tid = _pick_best_task(hub, category)
                if tid is None:
                    console.print("[yellow]No open tasks available. Waiting 30s...[/yellow]")
                    time.sleep(30)
                    continue

            # Join if needed
            try:
                hub.join_task(tid)
                console.print(f"[green]Joined task {tid}[/green]")
            except HubError as e:
                if e.status != 409:  # already joined
                    raise

            # Get task details with enriched prompt
            task_data = hub.get_task(tid, enriched=True)
            task = task_data.get("task", task_data)
            program_md = task.get("program_md", "")
            enriched_prompt = task_data.get("enriched_prompt", "")
            task_category = task.get("category", "")

            if not program_md:
                console.print(f"[yellow]Task {tid} has no program_md, skipping[/yellow]")
                continue

            title = task.get("title", "unnamed")
            console.print(f"[blue]Working on task {tid}: {title}[/blue]")
            if task_category:
                console.print(f"[dim]Category: {task_category}[/dim]")
            if enriched_prompt:
                console.print("[dim]Using enriched prompt with checklist[/dim]")
            if use_tools:
                console.print("[dim]Tools enabled: web_search, fetch_url[/dim]")

            # Generate patch via LLM
            console.print("[dim]Generating patch via LLM...[/dim]")
            patch_content = generate_patch(
                llm,
                cfg.llm.model,
                program_md,
                enriched_prompt=enriched_prompt,
                use_tools=use_tools,
            )
            if not patch_content.strip():
                console.print("[yellow]LLM returned empty patch, retrying...[/yellow]")
                continue

            console.print(f"[dim]Patch: {len(patch_content)} chars[/dim]")

            # Submit patch
            try:
                result = hub.submit_patch(tid, patch_content)
                patch_id = result.get("id", result.get("patch_id", "?"))
                console.print(f"[green]Submitted patch {patch_id}[/green]")
            except HubError as e:
                console.print(f"[red]Submit failed: {e.detail}[/red]")
                continue

            # Brief pause between rounds
            time.sleep(5)

    except KeyboardInterrupt:
        console.print("\n[yellow]Worker stopped by user[/yellow]")
    finally:
        hub.close()


def _pick_best_task(hub: HubClient, category: str = "") -> int | None:
    """Pick the open task with highest reward_karma, optionally filtered by category."""
    tasks = hub.list_tasks(status="open", category=category)
    if not tasks:
        return None
    best = max(tasks, key=lambda t: t.get("reward_karma", 0))
    return best["id"]
