"""Audit trail CLI commands."""

import json
from pathlib import Path

import typer

from fliiq.cli import display
from fliiq.runtime.agent.audit import AgentAuditTrail

audit_app = typer.Typer(help="View agent audit trails")


def _audit_dir() -> Path:
    from fliiq.runtime.config import resolve_fliiq_dir

    try:
        return resolve_fliiq_dir() / "audit"
    except FileNotFoundError:
        display.print_error("No .fliiq/ directory found. Run `fliiq init` first.")
        raise typer.Exit(1)


def _load_trail(path: Path) -> AgentAuditTrail:
    """Load an audit trail JSON, tolerant of old files missing new fields."""
    data = json.loads(path.read_text())
    return AgentAuditTrail.model_validate(data)


@audit_app.command("list")
def list_audits(
    limit: int = typer.Option(20, "--limit", "-n", help="Number of recent audits to show"),
):
    """List recent audit trails."""
    audit_path = _audit_dir()
    if not audit_path.is_dir():
        display.console.print("No audit trails found.")
        return

    files = sorted(audit_path.glob("*.json"), reverse=True)[:limit]
    if not files:
        display.console.print("No audit trails found.")
        return

    rows = []
    for f in files:
        try:
            trail = _load_trail(f)
        except Exception:
            continue

        ts = trail.started_at.strftime("%Y-%m-%d %H:%M")
        prompt_preview = trail.prompt[:60].replace("\n", " ")
        if len(trail.prompt) > 60:
            prompt_preview += "..."
        tokens = f"{trail.input_tokens + trail.output_tokens}" if (trail.input_tokens or trail.output_tokens) else "-"
        model = trail.model or "-"
        rows.append([
            ts,
            trail.id,
            prompt_preview,
            str(trail.total_iterations),
            tokens,
            model,
        ])

    display.print_table(
        ["Time", "ID", "Prompt", "Iters", "Tokens", "Model"],
        rows,
        title="Audit Trails",
    )


@audit_app.command("show")
def show_audit(
    audit_id: str = typer.Argument(..., help="Audit ID (12-char hex) or filename prefix"),
    as_json: bool = typer.Option(False, "--json", help="Output raw JSON"),
):
    """Show full detail of an audit trail."""
    audit_path = _audit_dir()
    if not audit_path.is_dir():
        display.print_error("No audit trails found.")
        raise typer.Exit(1)

    # Find matching file
    match = None
    for f in audit_path.glob("*.json"):
        if audit_id in f.stem:
            match = f
            break

    if not match:
        display.print_error(f"No audit trail matching '{audit_id}'.")
        raise typer.Exit(1)

    if as_json:
        display.console.print(match.read_text())
        return

    trail = _load_trail(match)

    display.console.print(f"[bold]ID:[/bold]         {trail.id}")
    display.console.print(f"[bold]Prompt:[/bold]     {trail.prompt}")
    display.console.print(f"[bold]Model:[/bold]      {trail.model or '-'}")
    display.console.print(f"[bold]Provider:[/bold]   {trail.provider or '-'}")
    display.console.print(f"[bold]Tokens:[/bold]     {trail.input_tokens} in / {trail.output_tokens} out")
    display.console.print(f"[bold]Iterations:[/bold] {trail.total_iterations}")
    display.console.print(f"[bold]Stop:[/bold]       {trail.stop_reason}")
    started = trail.started_at.strftime("%Y-%m-%d %H:%M:%S")
    completed = trail.completed_at.strftime("%Y-%m-%d %H:%M:%S") if trail.completed_at else "-"
    display.console.print(f"[bold]Started:[/bold]    {started}")
    display.console.print(f"[bold]Completed:[/bold]  {completed}")

    if trail.warnings:
        display.console.print()
        for w in trail.warnings:
            display.console.print(f"[yellow]{w}[/yellow]")

    display.console.print()
    display.console.print("[bold]Entries:[/bold]")
    for i, entry in enumerate(trail.entries, 1):
        role_color = "cyan" if entry.role == "assistant" else "green"
        ts = entry.timestamp.strftime("%H:%M:%S")
        duration = f" ({entry.duration_ms:.0f}ms)" if entry.duration_ms else ""
        display.console.print(f"  [{role_color}]{i}. {entry.role}[/{role_color}] {ts}{duration}")

        if entry.content_summary:
            display.console.print(f"     {entry.content_summary[:200]}")

        for tc in entry.tool_calls:
            name = tc.get("name", "?")
            tool_input = tc.get("input", tc.get("input_keys", {}))
            if isinstance(tool_input, dict):
                input_str = ", ".join(f"{k}={_truncate(str(v), 80)}" for k, v in tool_input.items())
            else:
                input_str = str(tool_input)
            display.console.print(f"     [dim]tool: {name}({input_str})[/dim]")

        for tr in entry.tool_results:
            preview = tr.get("content_preview", "")
            display.console.print(f"     [dim]result: {preview}[/dim]")

    if trail.final_text:
        display.console.print()
        display.console.print("[bold]Final Response:[/bold]")
        display.console.print(trail.final_text[:500])
        if len(trail.final_text) > 500:
            display.console.print(f"[dim]... +{len(trail.final_text) - 500} chars[/dim]")


def _truncate(s: str, max_len: int) -> str:
    return s[:max_len] + "..." if len(s) > max_len else s
