"""CLI command for viewing agent logs."""

from __future__ import annotations

from pathlib import Path

import typer

from terminaluse.lib.cli.utils.errors import CLIError, ErrorCode, ExitCode

# Valid log levels in severity order (least to most severe)
VALID_LEVELS = ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL")


def _resolve_agent_name(agent_name: str | None) -> str:
    """Resolve agent name from argument or config.yaml.

    Args:
        agent_name: Explicit agent name, or None to auto-detect.

    Returns:
        Agent name in 'namespace/agent-name' format.

    Raises:
        CLIError: If no agent name provided and no config.yaml found.
    """
    if agent_name is not None:
        return agent_name

    # Auto-detect from config.yaml in current directory
    config_path = Path("config.yaml")
    if not config_path.exists():
        raise CLIError(
            message="No agent specified and no config.yaml found in current directory",
            code=ErrorCode.NOT_FOUND,
            exit_code=ExitCode.NOT_FOUND,
            hint="Provide agent name: tu logs <namespace/agent>, or run from an agent directory",
        )

    from terminaluse.lib.sdk.config.agent_manifest import AgentManifest

    config_obj = AgentManifest.from_yaml(str(config_path))
    return config_obj.agent.name


def logs(
    agent_name: str | None = typer.Argument(
        None, help="Agent name (namespace/name). Omit to auto-detect from config.yaml"
    ),
    task: str | None = typer.Option(None, "--task", help="Filter by task ID"),
    level: str | None = typer.Option(
        None, "--level", "-l", help="Minimum log level: DEBUG, INFO, WARNING, ERROR, CRITICAL"
    ),
    source: str | None = typer.Option(None, "--source", help="Filter by source (stdout, stderr, server)"),
    since: str | None = typer.Option(None, "--since", help="Start time (e.g., 1h, 30m, 2d, or ISO 8601)"),
    until: str | None = typer.Option(None, "--until", help="End time (e.g., 1h, 30m, 2d, or ISO 8601)"),
    version: str | None = typer.Option(None, "--version", "-v", help="Filter by agent version ID"),
    limit: int = typer.Option(500, "--limit", "-n", help="Maximum number of logs to fetch"),
    follow: bool = typer.Option(False, "--follow", "-f", help="Stream new logs in real-time (like tail -f)"),
) -> None:
    """
    View logs for an agent.

    If run from an agent directory (with config.yaml), the agent is auto-detected.

    Examples:
        tu logs                                            # Auto-detect from config.yaml
        tu logs --since 1h                                 # Auto-detect + filter
        tu logs -f                                         # Auto-detect + stream
        tu logs myorg/my-agent                             # Explicit agent
        tu logs myorg/my-agent --since 1h --level WARNING
        tu logs myorg/my-agent --task task_abc123 --source stderr

    The --level flag uses minimum severity: --level WARNING shows WARNING,
    ERROR, and CRITICAL logs.

    Output modes:
        TTY (terminal):  Colorized, human-readable format
        Non-TTY (piped): Streams JSONL to stdout for pipeline consumption

    Streaming mode (-f):
        Streams only NEW logs after connection (like tail -f).
        Auto-disconnects after 5 minutes for cost control.
        --since, --until, and --limit are ignored in streaming mode.
    """
    from terminaluse.lib.cli.handlers.log_handlers import fetch_logs, stream_logs

    # Resolve agent name (from argument or config.yaml)
    resolved_agent_name = _resolve_agent_name(agent_name)

    # Validate and normalize level
    normalized_level = None
    if level:
        normalized_level = _normalize_level(level)

    if follow:
        # Streaming mode: --since, --until, --limit don't make sense
        stream_logs(
            agent_name=resolved_agent_name,
            task_id=task,
            level=normalized_level,
            source=source,
            version=version,
        )
    else:
        # Batch mode: fetch historical logs
        fetch_logs(
            agent_name=resolved_agent_name,
            task_id=task,
            level=normalized_level,
            source=source,
            since=since,
            until=until,
            version=version,
            limit=limit,
        )


def _normalize_level(level: str) -> str:
    """Normalize and validate log level input.

    Handles common variations like WARN -> WARNING, err -> ERROR.

    Args:
        level: User-provided level string.

    Returns:
        Normalized level string (uppercase, full name).

    Raises:
        typer.BadParameter: If level is not recognized.
    """
    normalized = level.upper().strip()

    # Handle common abbreviations
    aliases = {
        "WARN": "WARNING",
        "ERR": "ERROR",
        "CRIT": "CRITICAL",
        "FATAL": "CRITICAL",
    }
    normalized = aliases.get(normalized, normalized)

    if normalized not in VALID_LEVELS:
        raise typer.BadParameter(f"Invalid level '{level}'. Valid levels: {', '.join(VALID_LEVELS)}")

    return normalized
