"""
Audit Models - DSGVO-compliant logging
NO PII in audit logs - only references and metadata

Erlaubt: ref_id (truncated), content_type, size_bytes, ttl_hours
Verboten: user_name, content, transcript, email
"""
from datetime import datetime
from enum import Enum
from typing import Optional, Dict, Any
from pydantic import BaseModel, Field
import uuid


class AuditAction(str, Enum):
    """Audit action types."""
    # Session actions
    SESSION_CREATED = "session_created"
    SESSION_CONNECTED = "session_connected"
    SESSION_CLOSED = "session_closed"
    SESSION_EXPIRED = "session_expired"

    # Audio actions (no content logged)
    AUDIO_RECEIVED = "audio_received"
    AUDIO_PROCESSED = "audio_processed"

    # Task actions
    TASK_CREATED = "task_created"
    TASK_QUEUED = "task_queued"
    TASK_STARTED = "task_started"
    TASK_COMPLETED = "task_completed"
    TASK_FAILED = "task_failed"
    TASK_EXPIRED = "task_expired"

    # Encryption actions
    ENCRYPTION_KEY_VERIFIED = "encryption_key_verified"
    ENCRYPTION_KEY_INVALID = "encryption_key_invalid"

    # Integration actions
    BREAKPILOT_CALLED = "breakpilot_called"
    PERSONAPLEX_CALLED = "personaplex_called"
    OLLAMA_CALLED = "ollama_called"

    # Security actions
    RATE_LIMIT_EXCEEDED = "rate_limit_exceeded"
    UNAUTHORIZED_ACCESS = "unauthorized_access"


class AuditEntry(BaseModel):
    """
    Audit log entry - DSGVO compliant.
    NO PII is stored - only truncated references and metadata.
    """
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    timestamp: datetime = Field(default_factory=datetime.utcnow)

    # Action identification
    action: AuditAction
    namespace_id_truncated: str = Field(
        ...,
        description="First 8 chars of namespace ID",
        max_length=8,
    )

    # Reference IDs (truncated for privacy)
    session_id_truncated: Optional[str] = Field(
        default=None,
        description="First 8 chars of session ID",
        max_length=8,
    )
    task_id_truncated: Optional[str] = Field(
        default=None,
        description="First 8 chars of task ID",
        max_length=8,
    )

    # Metadata (no PII)
    content_type: Optional[str] = Field(default=None, description="Type of content processed")
    size_bytes: Optional[int] = Field(default=None, description="Size in bytes")
    duration_ms: Optional[int] = Field(default=None, description="Duration in milliseconds")
    ttl_hours: Optional[int] = Field(default=None, description="TTL in hours")

    # Technical metadata
    success: bool = Field(default=True)
    error_code: Optional[str] = Field(default=None)
    latency_ms: Optional[int] = Field(default=None)

    # Context (no PII)
    device_type: Optional[str] = Field(default=None)
    client_version: Optional[str] = Field(default=None)
    backend_used: Optional[str] = Field(default=None, description="personaplex, ollama, etc.")

    @staticmethod
    def truncate_id(full_id: str, length: int = 8) -> str:
        """Truncate ID for privacy."""
        if not full_id:
            return ""
        return full_id[:length]

    class Config:
        json_schema_extra = {
            "example": {
                "id": "audit-123",
                "timestamp": "2026-01-26T10:30:00Z",
                "action": "task_completed",
                "namespace_id_truncated": "teacher-",
                "session_id_truncated": "session-",
                "task_id_truncated": "task-xyz",
                "content_type": "student_observation",
                "size_bytes": 256,
                "ttl_hours": 168,
                "success": True,
                "latency_ms": 1250,
                "backend_used": "ollama",
            }
        }


class AuditCreate(BaseModel):
    """Request to create an audit entry."""
    action: AuditAction
    namespace_id: str = Field(..., description="Will be truncated before storage")
    session_id: Optional[str] = Field(default=None, description="Will be truncated")
    task_id: Optional[str] = Field(default=None, description="Will be truncated")
    content_type: Optional[str] = Field(default=None)
    size_bytes: Optional[int] = Field(default=None)
    duration_ms: Optional[int] = Field(default=None)
    success: bool = Field(default=True)
    error_code: Optional[str] = Field(default=None)
    latency_ms: Optional[int] = Field(default=None)
    device_type: Optional[str] = Field(default=None)
    backend_used: Optional[str] = Field(default=None)

    def to_audit_entry(self) -> AuditEntry:
        """Convert to AuditEntry with truncated IDs."""
        return AuditEntry(
            action=self.action,
            namespace_id_truncated=AuditEntry.truncate_id(self.namespace_id),
            session_id_truncated=AuditEntry.truncate_id(self.session_id) if self.session_id else None,
            task_id_truncated=AuditEntry.truncate_id(self.task_id) if self.task_id else None,
            content_type=self.content_type,
            size_bytes=self.size_bytes,
            duration_ms=self.duration_ms,
            success=self.success,
            error_code=self.error_code,
            latency_ms=self.latency_ms,
            device_type=self.device_type,
            backend_used=self.backend_used,
        )
