"""CLI commands for audit logging (SEC7).

Provides ``agents audit`` with subcommands for listing, viewing,
and pruning audit log entries.
"""

from __future__ import annotations

import json
from typing import TYPE_CHECKING, Annotated

import typer

from cleveragents.cli.main import get_console, get_err_console

if TYPE_CHECKING:
    from cleveragents.application.services.audit_service import (
        AuditLogEntry,
        AuditService,
    )

app = typer.Typer(
    help="View and manage the audit log for security-relevant operations.",
)


def _get_audit_service() -> AuditService:
    """Build an :class:`AuditService` from current settings."""
    from cleveragents.application.services.audit_service import AuditService
    from cleveragents.config.settings import get_settings

    return AuditService(settings=get_settings())


@app.command(name="list")
def list_entries(
    plan: Annotated[
        str | None,
        typer.Option("--plan", help="Filter by plan ID."),
    ] = None,
    project: Annotated[
        str | None,
        typer.Option("--project", help="Filter by project name."),
    ] = None,
    event_type: Annotated[
        str | None,
        typer.Option("--type", help="Filter by event type."),
    ] = None,
    since: Annotated[
        str | None,
        typer.Option(
            "--since",
            help="Only entries after this ISO-8601 timestamp.",
        ),
    ] = None,
    limit: Annotated[
        int,
        typer.Option("--limit", "-n", help="Maximum entries to display."),
    ] = 50,
) -> None:
    """List audit log entries with optional filters."""
    console = get_console()

    with _get_audit_service() as service:
        entries = service.list_entries(
            plan_id=plan,
            project_name=project,
            event_type=event_type,
            since=since,
            limit=limit,
        )

    if not entries:
        console.print("[dim]No audit entries found.[/dim]")
        return

    console.print(f"\n[bold]Audit Log ({len(entries)} entries)[/bold]\n")
    for entry in entries:
        _print_entry_summary(entry)
    console.print()


@app.command(name="show")
def show_entry(
    audit_id: Annotated[
        int,
        typer.Argument(help="The audit entry ID to display."),
    ],
) -> None:
    """Show a single audit entry with full metadata."""
    console = get_console()
    err_console = get_err_console()

    with _get_audit_service() as service:
        entry = service.get_entry(audit_id)

    if entry is None:
        err_console.print(f"[red]Audit entry {audit_id} not found.[/red]")
        raise typer.Exit(code=1)

    console.print(f"\n[bold]Audit Entry #{entry.id}[/bold]\n")
    console.print(f"  Event type:     {entry.event_type}")
    console.print(f"  Created at:     {entry.created_at}")
    console.print(f"  Plan ID:        {entry.plan_id or '-'}")
    console.print(f"  Project:        {entry.project_name or '-'}")
    console.print(f"  Actor:          {entry.actor_name or '-'}")
    console.print(f"  User:           {entry.user_identity or '-'}")
    console.print("  Details:")
    if entry.details:
        for line in json.dumps(entry.details, indent=2).splitlines():
            console.print(f"    {line}")
    else:
        console.print("    (none)")
    console.print()


@app.command(name="prune")
def prune(
    days: Annotated[
        int | None,
        typer.Option(
            "--days",
            help="Delete entries older than this many days. Overrides config.",
        ),
    ] = None,
    yes: Annotated[
        bool,
        typer.Option("--yes", "-y", help="Skip confirmation prompt."),
    ] = False,
) -> None:
    """Delete audit entries older than the retention period."""
    console = get_console()
    err_console = get_err_console()

    if not yes:
        from cleveragents.config.settings import get_settings

        effective_days = (
            days if days is not None else get_settings().audit_retention_days
        )
        if effective_days <= 0:
            console.print(
                "[dim]Retention is set to 0 (keep everything). Nothing to prune.[/dim]"
            )
            return
        confirm = typer.confirm(
            f"Delete audit entries older than {effective_days} days?"
        )
        if not confirm:
            err_console.print("[yellow]Aborted.[/yellow]")
            raise typer.Abort()

    with _get_audit_service() as service:
        deleted = service.prune(retention_days=days)
    console.print(f"[green]Pruned {deleted} audit log entries.[/green]")


@app.command(name="count")
def count_entries() -> None:
    """Show the total number of audit log entries."""
    console = get_console()
    with _get_audit_service() as service:
        total = service.count()
    console.print(f"Total audit log entries: {total}")


# ── Helpers ───────────────────────────────────────────────────────


def _print_entry_summary(entry: AuditLogEntry) -> None:
    """Print a one-line summary of an audit entry."""
    console = get_console()
    plan_info = f" plan={entry.plan_id}" if entry.plan_id else ""
    project_info = f" project={entry.project_name}" if entry.project_name else ""
    console.print(
        f"  [dim]#{entry.id}[/dim] "
        f"[bold]{entry.event_type}[/bold]"
        f"{plan_info}{project_info} "
        f"[dim]{entry.created_at}[/dim]"
    )
