"""Agent audit — extract structured audit trail from message history."""

from datetime import datetime, timezone
from pathlib import Path
from uuid import uuid4

import structlog
from pydantic import BaseModel, Field

log = structlog.get_logger()


class AuditEntry(BaseModel):
    timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
    role: str
    content_summary: str
    tool_calls: list[dict] = Field(default_factory=list)
    tool_results: list[dict] = Field(default_factory=list)


class AgentAuditTrail(BaseModel):
    id: str = Field(default_factory=lambda: uuid4().hex[:12])
    prompt: str
    entries: list[AuditEntry] = Field(default_factory=list)
    final_text: str = ""
    total_iterations: int = 0
    stop_reason: str = ""
    started_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
    completed_at: datetime | None = None
    warnings: list[str] = Field(default_factory=list)


def extract_audit_trail(prompt: str, messages: list[dict], stop_reason: str = "") -> AgentAuditTrail:
    """Walk message history and extract a structured audit trail."""
    trail = AgentAuditTrail(prompt=prompt, stop_reason=stop_reason)
    iterations = 0

    for msg in messages:
        role = msg.get("role", "unknown")
        entry = AuditEntry(role=role, content_summary="")

        content = msg.get("content", "")

        if isinstance(content, str):
            entry.content_summary = content[:200] if content else ""
        elif isinstance(content, list):
            # Content blocks (Anthropic format)
            summaries = []
            for block in content:
                if isinstance(block, dict):
                    if block.get("type") == "text":
                        summaries.append(block.get("text", "")[:100])
                    elif block.get("type") == "tool_use":
                        entry.tool_calls.append({
                            "id": block.get("id"),
                            "name": block.get("name"),
                            "input_keys": list(block.get("input", {}).keys()),
                        })
                    elif block.get("type") == "tool_result":
                        entry.tool_results.append({
                            "tool_use_id": block.get("tool_use_id"),
                            "content_preview": str(block.get("content", ""))[:100],
                        })
            entry.content_summary = " | ".join(summaries) if summaries else ""

        if role == "assistant":
            iterations += 1

        trail.entries.append(entry)

    trail.total_iterations = iterations
    trail.completed_at = datetime.now(timezone.utc)
    return trail


def detect_confabulation(trail: AgentAuditTrail) -> list[str]:
    """Analyze audit trail for confabulation patterns. Returns list of warnings."""
    warnings = []
    execution_tools = {"shell", "write_file", "edit_file"}

    tool_names_used = set()
    has_todo_done = False
    for entry in trail.entries:
        for tc in entry.tool_calls:
            tool_names_used.add(tc["name"])
            if tc["name"] == "todo" and "status" in tc.get("input_keys", []):
                has_todo_done = True

    has_execution = bool(tool_names_used & execution_tools)

    if has_todo_done and not has_execution:
        warnings.append(
            "WARNING: Tasks were marked complete but no execution tools "
            "(shell, write_file, edit_file) were used. "
            "The agent may have confabulated results."
        )

    return warnings


def save_audit_trail(trail: AgentAuditTrail, audit_dir: Path | None = None) -> Path:
    """Save audit trail to .fliiq/audit/ as JSON. Returns file path."""
    if audit_dir is None:
        from fliiq.runtime.config import resolve_fliiq_dir

        try:
            audit_dir = resolve_fliiq_dir() / "audit"
        except FileNotFoundError:
            audit_dir = Path(".fliiq/audit")
    audit_dir.mkdir(parents=True, exist_ok=True)

    ts = trail.started_at.strftime("%Y%m%d_%H%M%S")
    filename = f"{ts}_{trail.id}.json"
    path = audit_dir / filename

    path.write_text(trail.model_dump_json(indent=2))
    log.info("agent_audit_saved", path=str(path))
    return path
