"""
Structured Audit Logger

Logs every tool execution with full context for compliance and debugging.
Output goes to stdout (captured by `docker logs`).
"""

import json
import logging
import time
from dataclasses import dataclass, asdict
from typing import Optional, Dict, Any

logger = logging.getLogger("audit")


@dataclass
class AuditEntry:
    """A single audit log entry."""
    timestamp: str
    request_id: str
    agent_id: str
    agent_name: str
    tool: str
    tool_type: str         # "local" or "service"
    action: str            # "execute", "credential_sync", "policy_update"
    status: str            # "started", "success", "denied", "error", "timeout"
    duration_ms: int = 0
    params_summary: str = ""
    output_preview: str = ""
    error: str = ""
    security_reason: str = ""  # If denied, why
    metadata: Dict[str, Any] = None


class AuditLogger:
    """
    Structured audit logger for all workspace agent activity.
    
    Every tool execution, credential sync, and policy update is logged.
    Logs are JSON-structured and go to stdout for `docker logs` consumption.
    """

    def __init__(self, log_level: str = "full"):
        """
        Args:
            log_level: "full" (all details), "summary" (no params/output), 
                       "errors_only" (only failures)
        """
        self._log_level = log_level
        self._handler = logging.StreamHandler()
        self._handler.setFormatter(logging.Formatter("%(message)s"))
        logger.addHandler(self._handler)
        logger.setLevel(logging.INFO)

    def log_execution_start(self, request_id: str, agent_id: str, agent_name: str,
                            tool: str, tool_type: str, params: Dict[str, Any]):
        """Log when a tool execution begins."""
        if self._log_level == "errors_only":
            return

        entry = AuditEntry(
            timestamp=self._now(),
            request_id=request_id,
            agent_id=agent_id,
            agent_name=agent_name,
            tool=tool,
            tool_type=tool_type,
            action="execute",
            status="started",
            params_summary=self._summarize_params(params) if self._log_level == "full" else "",
        )
        self._emit(entry)

    def log_execution_result(self, request_id: str, agent_id: str, agent_name: str,
                             tool: str, tool_type: str, success: bool,
                             output: str = "", error: str = "", duration_ms: int = 0):
        """Log tool execution completion."""
        status = "success" if success else "error"
        if self._log_level == "errors_only" and success:
            return

        entry = AuditEntry(
            timestamp=self._now(),
            request_id=request_id,
            agent_id=agent_id,
            agent_name=agent_name,
            tool=tool,
            tool_type=tool_type,
            action="execute",
            status=status,
            duration_ms=duration_ms,
            output_preview=output[:200] if self._log_level == "full" else "",
            error=error,
        )
        self._emit(entry)

    def log_denied(self, request_id: str, agent_id: str, agent_name: str,
                   tool: str, reason: str):
        """Log when a tool execution is denied by security."""
        entry = AuditEntry(
            timestamp=self._now(),
            request_id=request_id,
            agent_id=agent_id,
            agent_name=agent_name,
            tool=tool,
            tool_type="",
            action="execute",
            status="denied",
            security_reason=reason,
        )
        self._emit(entry)

    def log_credential_sync(self, service_slug: str, action: str = "store"):
        """Log credential sync events."""
        entry = AuditEntry(
            timestamp=self._now(),
            request_id="",
            agent_id="",
            agent_name="",
            tool=service_slug,
            tool_type="credential",
            action=f"credential_{action}",
            status="success",
        )
        self._emit(entry)

    def log_connection(self, status: str, metadata: Dict[str, Any] = None):
        """Log connection lifecycle events."""
        entry = AuditEntry(
            timestamp=self._now(),
            request_id="",
            agent_id="",
            agent_name="",
            tool="",
            tool_type="system",
            action="connection",
            status=status,
            metadata=metadata,
        )
        self._emit(entry)

    def _emit(self, entry: AuditEntry):
        """Write audit entry as JSON to stdout."""
        data = asdict(entry)
        # Remove None/empty values for cleaner output
        data = {k: v for k, v in data.items() if v is not None and v != "" and v != 0}
        logger.info(json.dumps(data))

    @staticmethod
    def _now() -> str:
        from datetime import datetime, timezone
        return datetime.now(timezone.utc).isoformat()

    @staticmethod
    def _summarize_params(params: Dict[str, Any]) -> str:
        """Create a safe summary of params (truncate long values)."""
        summary = {}
        for k, v in params.items():
            sv = str(v)
            summary[k] = sv[:100] + "..." if len(sv) > 100 else sv
        return json.dumps(summary)
