"""Serve CLI commands - serve, test-live."""
from __future__ import annotations

import json
from pathlib import Path
from typing import TYPE_CHECKING, Any

import click
import httpx

from ..utils.animation import run_sync_coro

if TYPE_CHECKING:
    pass


@click.command()
@click.option("--host", "-h", default="0.0.0.0", help="Host to bind to")
@click.option("--port", "-p", default=8000, type=int, help="Port to bind to")
@click.option("--reload", "-r", is_flag=True, help="Enable auto-reload")
@click.option(
    "--agents",
    "-a",
    "agent_configs",
    multiple=True,
    type=click.Path(exists=True, path_type=Path),
    help="Agent config files (can be specified multiple times)",
)
@click.option("--api-key", help="API key for authentication")
@click.option("--api-keys-json", help="JSON object mapping API keys to principals/scopes/workspaces")
@click.option("--require-workspace", is_flag=True, help="Require X-Workspace-Id for authenticated requests")
@click.option("--test", is_flag=True, help="Test all agents before starting server")
@click.option("--log", "-l", "log_file", type=click.Path(), help="Log file path")
@click.option(
    "--rate-limit/--no-rate-limit",
    default=True,
    help="Enable rate limiting",
)
@click.option("--rate-limit-per-minute", type=int, help="Rate limit per minute")
@click.option("--rate-limit-burst", type=int, help="Rate limit burst")
@click.option("--rate-limit-backend", type=click.Choice(["memory", "redis", "postgresql"]), help="Rate limit backend")
@click.option("--rate-limit-dsn", help="Rate limit DSN (Redis/PostgreSQL)")
@click.option("--chronos-autostart/--no-chronos-autostart", default=True, help="Auto-start Chronos scheduler")
def serve(
    host: str,
    port: int,
    reload: bool,
    agent_configs: tuple[Path, ...],
    api_key: str | None,
    api_keys_json: str | None,
    require_workspace: bool,
    test: bool,
    log_file: Path | None,
    rate_limit: bool,
    rate_limit_per_minute: int | None,
    rate_limit_burst: int | None,
    rate_limit_backend: str | None,
    rate_limit_dsn: str | None,
    chronos_autostart: bool,
) -> None:
    """Serve agents as a web API."""
    from logos_adk.serve import create_app
    
    if not agent_configs:
        click.echo(
            click.style("Error: At least one --agents config file is required", fg="red"),
            err=True,
        )
        raise SystemExit(1)
    
    agents = []
    for config_path in agent_configs:
        try:
            agent = run_sync_coro(load_agent_from_config_async(str(config_path)))
            agents.append(agent)
            click.echo(f"✓ Loaded agent: {agent.name}")
        except Exception as e:
            click.echo(
                click.style(f"✗ Failed to load {config_path}: {e}", fg="red"),
                err=True,
            )
            raise SystemExit(1)
    
    if test:
        click.echo("\nTesting agents...")
        for agent in agents:
            try:
                async def test_agent():
                    return await agent.run("test", session_id="cli-test")

                run_sync_coro(test_agent())
                click.echo(f"  ✓ {agent.name}: OK")
            except Exception as e:
                click.echo(click.style(f"  ✗ {agent.name}: {e}", fg="red"), err=True)
                raise SystemExit(1)
    
    api_keys = None
    if api_keys_json:
        try:
            parsed = json.loads(api_keys_json)
        except json.JSONDecodeError as exc:
            click.echo(
                click.style(f"✗ Invalid --api-keys-json: {exc}", fg="red"),
                err=True,
            )
            raise SystemExit(1)
        if not isinstance(parsed, dict):
            click.echo(
                click.style("✗ --api-keys-json must be a JSON object", fg="red"),
                err=True,
            )
            raise SystemExit(1)
        api_keys = parsed

    app = create_app(
        agents,
        api_key=api_key,
        api_keys=api_keys,
        require_workspace=require_workspace,
        rate_limit_enabled=rate_limit,
        rate_limit_per_minute=rate_limit_per_minute,
        rate_limit_burst=rate_limit_burst,
        rate_limit_backend=rate_limit_backend,
        rate_limit_dsn=rate_limit_dsn,
        chronos_autostart=chronos_autostart,
    )
    
    click.echo(f"\n🚀 Starting server on http://{host}:{port}")
    click.echo(f"   Agents: {', '.join(a.name for a in agents)}")
    
    if reload:
        click.echo("   Auto-reload: enabled")
    
    if log_file:
        click.echo(f"   Log file: {log_file}")
    
    import uvicorn
    uvicorn.run(app, host=host, port=port, reload=reload)


@click.command()
@click.argument("url", default="http://localhost:8000")
@click.argument("prompt")
@click.option("--agent", "-a", help="Agent name (required if multiple agents)")
@click.option("--stream/--no-stream", default=False, help="Enable streaming")
def test_live(url: str, prompt: str, agent: str | None, stream: bool) -> None:
    """Test a live agent via HTTP."""
    endpoint = f"{url.rstrip('/')}/{'stream' if stream else 'run'}"
    
    payload = {"prompt": prompt}
    if agent:
        payload["agent_name"] = agent
    
    headers = {"Content-Type": "application/json"}
    
    click.echo(f"Testing {endpoint}...")
    click.echo(f"Prompt: {prompt}")
    if agent:
        click.echo(f"Agent: {agent}")
    click.echo()
    
    try:
        if stream:
            response = httpx.post(endpoint, json=payload, headers=headers, timeout=120.0)
            response.raise_for_status()
            
            for line in response.iter_lines():
                if line.startswith("data: "):
                    data = json.loads(line[6:])
                    if data.get("type") == "text":
                        click.echo(data.get("delta", ""), nl=False)
                    elif data.get("type") == "done":
                        click.echo()
                        break
        else:
            response = httpx.post(endpoint, json=payload, headers=headers, timeout=120.0)
            response.raise_for_status()
            
            result = response.json()
            click.echo(click.style("Response:", fg="green", bold=True))
            click.echo(result.get("content", ""))
            
            if "usage" in result:
                usage = result["usage"]
                click.echo(
                    click.style(
                        f"\n[Tokens: {usage.get('input_tokens', 0)} in, {usage.get('output_tokens', 0)} out]",
                        fg="yellow",
                    )
                )
    
    except httpx.HTTPError as e:
        click.echo(click.style(f"HTTP Error: {e}", fg="red"), err=True)
        raise SystemExit(1)
    except Exception as e:
        click.echo(click.style(f"Error: {e}", fg="red"), err=True)
        raise SystemExit(1)


async def load_agent_from_config_async(config_path: str) -> Any:
    """Load agent from config file asynchronously."""
    from logos_adk.runnable_config_loader import load_runnable_from_config
    
    # Use sync version for now
    return load_runnable_from_config(config_path)


__all__ = ["serve", "test_live"]
