"""
Jobs command group for managing background jobs.

Commands:
- list: Show recent jobs
- status: Check status of one or more jobs
- wait: Wait for jobs to complete (for scripting/Claude Code)
- download: Download artifacts for a completed job
"""

import json
import time
from pathlib import Path
from typing import Optional

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

app = typer.Typer(no_args_is_help=True)
console = Console()


@app.command("list")
def list_jobs(
    limit: int = typer.Option(
        20,
        "--limit",
        "-n",
        help="Maximum number of jobs to show",
    ),
    json_output: bool = typer.Option(
        False,
        "--json",
        help="Output as JSON",
    ),
):
    """
    List recent jobs.

    Shows jobs from the current session. Jobs are stored locally
    and persist across CLI invocations.

    Examples:
        amina jobs list
        amina jobs list --limit 50
        amina jobs list --json
    """
    from amina_cli.auth import get_job_history

    try:
        jobs = get_job_history(limit=limit)
    except Exception:
        jobs = []

    if not jobs:
        console.print("[dim]No jobs found. Submit jobs with --background flag.[/dim]")
        return

    if json_output:
        console.print(json.dumps(jobs, indent=2, default=str))
        return

    table = Table(title="Recent Jobs")
    table.add_column("Job ID", style="cyan", no_wrap=True)
    table.add_column("Tool", style="green")
    table.add_column("Status", style="yellow")
    table.add_column("Submitted", style="dim")

    for job in jobs:
        table.add_row(
            job.get("job_id", "")[:8] + "...",
            job.get("tool_name", "unknown"),
            job.get("status", "unknown"),
            job.get("submitted_at", ""),
        )

    console.print(table)


@app.command("status")
def status(
    job_ids: list[str] = typer.Argument(
        ...,
        help="Job ID(s) to check status for",
    ),
    json_output: bool = typer.Option(
        False,
        "--json",
        help="Output as JSON (useful for scripting)",
    ),
):
    """
    Check status of one or more jobs.

    Accepts full or partial job IDs. Queries the server for current status.

    Examples:
        amina jobs status abc123
        amina jobs status abc123 def456 ghi789
        amina jobs status abc123 --json
    """
    from amina_cli.auth import get_job_info
    from amina_cli.client import check_job_status_sync, ToolExecutionError

    results = []

    for job_id in job_ids:
        # Look up job info from local storage
        job_info = get_job_info(job_id)

        if not job_info:
            results.append(
                {
                    "job_id": job_id,
                    "status": "not_found",
                    "error": "Job not found in local history. Use full job ID.",
                }
            )
            continue

        # Query server for current status
        try:
            status_result = check_job_status_sync(
                call_id=job_info.get("call_id", ""),
                job_id=job_info.get("job_id", job_id),
                user_id=job_info.get("user_id", ""),
                tool_name=job_info.get("tool_name", ""),
            )
            results.append(
                {
                    "job_id": job_info.get("job_id", job_id),
                    "tool_name": job_info.get("tool_name", ""),
                    **status_result,
                }
            )
        except ToolExecutionError as e:
            results.append(
                {
                    "job_id": job_id,
                    "status": "error",
                    "error": str(e),
                }
            )

    if json_output:
        console.print(json.dumps(results, indent=2, default=str))
        return

    # Display as table
    for result in results:
        job_id = result.get("job_id", "")[:8]
        status_str = result.get("status", "unknown")
        tool_name = result.get("tool_name", "")

        if status_str == "running":
            console.print(f"[yellow]\u23f3[/yellow] {job_id}... ({tool_name}): [yellow]running[/yellow]")
        elif status_str == "completed":
            console.print(f"[green]\u2713[/green] {job_id}... ({tool_name}): [green]completed[/green]")
        elif status_str == "failed":
            error = result.get("error", "Unknown error")
            console.print(f"[red]\u2717[/red] {job_id}... ({tool_name}): [red]failed[/red] - {error}")
        elif status_str == "not_found":
            console.print(f"[dim]?[/dim] {job_id}...: [dim]not found[/dim]")
        else:
            console.print(f"[dim]?[/dim] {job_id}... ({tool_name}): [dim]{status_str}[/dim]")


@app.command("wait")
def wait(
    job_ids: list[str] = typer.Argument(
        ...,
        help="Job ID(s) to wait for",
    ),
    output_json: Optional[Path] = typer.Option(
        None,
        "--output-json",
        "-o",
        help="Write results to JSON file when complete",
    ),
    poll_interval: int = typer.Option(
        10,
        "--poll-interval",
        help="Seconds between status checks",
    ),
    timeout: int = typer.Option(
        3600,
        "--timeout",
        "-t",
        help="Maximum seconds to wait (default: 1 hour)",
    ),
):
    """
    Wait for jobs to complete.

    Polls the server until all jobs finish (success or failure).
    Useful for scripting and Claude Code integration.

    Examples:
        amina jobs wait abc123
        amina jobs wait abc123 def456 --output-json /tmp/results.json
        amina jobs wait abc123 --timeout 7200 --poll-interval 30
    """
    from amina_cli.auth import get_job_info
    from amina_cli.client import check_job_status_sync, ToolExecutionError

    start_time = time.time()
    pending_jobs = set(job_ids)
    results = {}

    console.print(f"Waiting for {len(job_ids)} job(s)...")

    while pending_jobs:
        elapsed = time.time() - start_time
        if elapsed > timeout:
            console.print(f"\n[red]Timeout after {timeout}s. Some jobs may still be running.[/red]")
            for job_id in pending_jobs:
                results[job_id] = {"status": "timeout", "error": "Timed out waiting for completion"}
            break

        for job_id in list(pending_jobs):
            job_info = get_job_info(job_id)

            if not job_info:
                results[job_id] = {"status": "not_found", "error": "Job not found in local history"}
                pending_jobs.discard(job_id)
                continue

            try:
                status_result = check_job_status_sync(
                    call_id=job_info.get("call_id", ""),
                    job_id=job_info.get("job_id", job_id),
                    user_id=job_info.get("user_id", ""),
                    tool_name=job_info.get("tool_name", ""),
                )

                if status_result.get("status") in ("completed", "failed"):
                    results[job_id] = {
                        "job_id": job_info.get("job_id", job_id),
                        "tool_name": job_info.get("tool_name", ""),
                        **status_result,
                    }
                    pending_jobs.discard(job_id)

                    status_str = status_result.get("status")
                    if status_str == "completed":
                        console.print(f"[green]\u2713[/green] {job_id[:8]}... completed")
                    else:
                        console.print(f"[red]\u2717[/red] {job_id[:8]}... failed")

            except ToolExecutionError as e:
                results[job_id] = {"status": "error", "error": str(e)}
                pending_jobs.discard(job_id)

        if pending_jobs:
            time.sleep(poll_interval)

    # Write results to file if requested
    if output_json:
        output_json.parent.mkdir(parents=True, exist_ok=True)
        output_json.write_text(json.dumps(results, indent=2, default=str))
        console.print(f"\n[dim]Results written to {output_json}[/dim]")

    # Summary
    completed = sum(1 for r in results.values() if r.get("status") == "completed")
    failed = sum(1 for r in results.values() if r.get("status") in ("failed", "error", "timeout", "not_found"))
    console.print(f"\n{completed} completed, {failed} failed")

    if failed > 0:
        raise typer.Exit(1)


@app.command("download")
def download(
    job_id: str = typer.Argument(
        ...,
        help="Job ID to download artifacts from",
    ),
    output: Path = typer.Option(
        ...,
        "--output",
        "-o",
        help="Output directory for downloaded files",
    ),
):
    """
    Download artifacts for a completed job.

    Fetches output files from a completed job and saves them locally.

    Examples:
        amina jobs download abc123 -o ./results/
    """
    from amina_cli.auth import get_job_info
    from amina_cli.client import check_job_status_sync, ToolExecutionError
    from amina_cli.storage import download_results, StorageError

    # Look up job info
    job_info = get_job_info(job_id)

    if not job_info:
        console.print(f"[red]Error:[/red] Job '{job_id}' not found in local history.")
        raise typer.Exit(1)

    # Check status
    try:
        status_result = check_job_status_sync(
            call_id=job_info.get("call_id", ""),
            job_id=job_info.get("job_id", job_id),
            user_id=job_info.get("user_id", ""),
            tool_name=job_info.get("tool_name", ""),
        )
    except ToolExecutionError as e:
        console.print(f"[red]Error checking job status:[/red] {e}")
        raise typer.Exit(1)

    if status_result.get("status") == "running":
        console.print("[yellow]Job is still running.[/yellow] Wait for completion first:")
        console.print(f"  amina jobs wait {job_id}")
        raise typer.Exit(1)

    if status_result.get("status") == "failed":
        console.print(f"[red]Job failed:[/red] {status_result.get('error', 'Unknown error')}")
        raise typer.Exit(1)

    if status_result.get("status") != "completed":
        console.print(f"[red]Unexpected job status:[/red] {status_result.get('status')}")
        raise typer.Exit(1)

    # Download results
    result = status_result.get("result", {})
    try:
        downloaded = download_results(result, output)
        if downloaded:
            console.print(f"[green]\u2713[/green] Downloaded {len(downloaded)} file(s) to {output}/")
            for path in downloaded:
                console.print(f"  - {path.name}")
        else:
            console.print("[dim]No output files to download.[/dim]")
    except StorageError as e:
        # Show signed URLs as fallback
        signed_urls = result.get("signed_urls", {})
        if signed_urls:
            console.print(f"[yellow]Warning:[/yellow] Could not download automatically: {e}")
            console.print("\n[bold]Files available at:[/bold]")
            for file_type, url in signed_urls.items():
                if url:
                    console.print(f"  {file_type}: {url}")
        else:
            console.print(f"[red]Download failed:[/red] {e}")
            raise typer.Exit(1)
