"""Pydantic models for audit logging."""

from datetime import datetime, timezone
from typing import Optional, Any
from pydantic import BaseModel, Field

from .enums import AuditAction, AuditResource, AuditResult, AuditSeverity


class AuditActor(BaseModel):
    """Who performed the action."""
    user_id: Optional[str] = None
    org_id: str
    api_key_hash: Optional[str] = None  # Hashed/masked API key
    ip_address: Optional[str] = None
    user_agent: Optional[str] = None


class AuditTarget(BaseModel):
    """What was acted upon."""
    resource_type: AuditResource
    resource_id: Optional[str] = None
    resource_name: Optional[str] = None


class AuditChange(BaseModel):
    """Track changes for update operations."""
    field: str
    old_value: Optional[Any] = None
    new_value: Optional[Any] = None


class GuardrailViolation(BaseModel):
    """Track guardrail/RAI violations."""
    violation_type: str  # pii, toxicity, injection, nsfw, keyword, banned_topic
    severity: AuditSeverity = AuditSeverity.MEDIUM
    details: Optional[dict] = None


class AuditLogEntry(BaseModel):
    """Main audit log entry model."""
    # Core identification
    timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))

    # Actor information (who)
    actor: AuditActor

    # Action information (what)
    action: AuditAction
    target: AuditTarget

    # Result
    result: AuditResult
    error_message: Optional[str] = None

    # Context
    session_id: Optional[str] = None
    request_id: Optional[str] = None
    permission_required: Optional[str] = None

    # Changes (for updates)
    changes: Optional[list[AuditChange]] = None

    # Guardrail violations
    guardrail_violations: Optional[list[GuardrailViolation]] = None

    # Additional metadata
    metadata: Optional[dict] = None

    # Severity for security-relevant events
    severity: AuditSeverity = AuditSeverity.LOW

    def to_document(self) -> dict:
        """Convert to MongoDB document format."""
        doc = self.model_dump(mode="json", exclude_none=True)
        # Ensure timestamp is in correct format
        if isinstance(doc.get("timestamp"), str):
            doc["timestamp"] = datetime.fromisoformat(doc["timestamp"].replace("Z", "+00:00"))
        return doc


class AuditLogQuery(BaseModel):
    """Query parameters for searching audit logs."""
    org_id: Optional[str] = None
    user_id: Optional[str] = None
    action: Optional[AuditAction] = None
    resource_type: Optional[AuditResource] = None
    resource_id: Optional[str] = None
    result: Optional[AuditResult] = None
    severity: Optional[AuditSeverity] = None
    start_time: Optional[datetime] = None
    end_time: Optional[datetime] = None
    session_id: Optional[str] = None
    limit: int = Field(default=100, le=1000)
    offset: int = Field(default=0, ge=0)
