# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
"""
Security models: Token and AuthEvent.

Multi-Tenant Design:
- Token ist NICHT an einen Mandanten gebunden
- User arbeitet parallel in mehreren Mandanten (z.B. mehrere Browser-Tabs)
- Mandant-Kontext wird per Request-Header (X-Mandate-Id) bestimmt
"""

from typing import Optional
from pydantic import BaseModel, Field, ConfigDict
from modules.shared.attributeUtils import registerModelLabels
from modules.shared.timeUtils import getUtcTimestamp
from .datamodelUam import AuthAuthority
from enum import Enum
import uuid


class TokenStatus(str, Enum):
    ACTIVE = "active"
    REVOKED = "revoked"


class Token(BaseModel):
    """
    Authentication Token model.
    
    Multi-Tenant Design:
    - Token ist User-gebunden, NICHT Mandant-gebunden
    - Ermöglicht parallele Arbeit in mehreren Mandanten
    - Mandant-Kontext wird per Request-Header bestimmt
    """
    id: Optional[str] = None
    userId: str
    authority: AuthAuthority
    connectionId: Optional[str] = Field(
        None, description="ID of the connection this token belongs to"
    )
    tokenAccess: str
    tokenType: str = "bearer"
    expiresAt: float = Field(
        description="When the token expires (UTC timestamp in seconds)"
    )
    tokenRefresh: Optional[str] = None
    createdAt: Optional[float] = Field(
        None, description="When the token was created (UTC timestamp in seconds)"
    )
    status: TokenStatus = Field(
        default=TokenStatus.ACTIVE, description="Token status: active/revoked"
    )
    revokedAt: Optional[float] = Field(
        None, description="When the token was revoked (UTC timestamp in seconds)"
    )
    revokedBy: Optional[str] = Field(
        None, description="User ID who revoked the token (admin/self)"
    )
    reason: Optional[str] = Field(None, description="Optional revocation reason")
    sessionId: Optional[str] = Field(
        None, description="Logical session grouping for logout revocation"
    )
    # ENTFERNT: mandateId - Token ist nicht mehr Mandant-spezifisch
    # Mandant-Kontext wird per Request-Header (X-Mandate-Id) bestimmt

    model_config = ConfigDict(use_enum_values=True)


registerModelLabels(
    "Token",
    {"en": "Token", "de": "Token", "fr": "Jeton"},
    {
        "id": {"en": "ID", "de": "ID", "fr": "ID"},
        "userId": {"en": "User ID", "de": "Benutzer-ID", "fr": "ID utilisateur"},
        "authority": {"en": "Authority", "de": "Autorität", "fr": "Autorité"},
        "connectionId": {"en": "Connection ID", "de": "Verbindungs-ID", "fr": "ID de connexion"},
        "tokenAccess": {"en": "Access Token", "de": "Zugriffstoken", "fr": "Jeton d'accès"},
        "tokenType": {"en": "Token Type", "de": "Token-Typ", "fr": "Type de jeton"},
        "expiresAt": {"en": "Expires At", "de": "Läuft ab am", "fr": "Expire le"},
        "tokenRefresh": {"en": "Refresh Token", "de": "Refresh-Token", "fr": "Jeton de rafraîchissement"},
        "createdAt": {"en": "Created At", "de": "Erstellt am", "fr": "Créé le"},
        "status": {"en": "Status", "de": "Status", "fr": "Statut"},
        "revokedAt": {"en": "Revoked At", "de": "Widerrufen am", "fr": "Révoqué le"},
        "revokedBy": {"en": "Revoked By", "de": "Widerrufen von", "fr": "Révoqué par"},
        "reason": {"en": "Reason", "de": "Grund", "fr": "Raison"},
        "sessionId": {"en": "Session ID", "de": "Sitzungs-ID", "fr": "ID de session"},
    },
)


class AuthEvent(BaseModel):
    """Authentication event for audit logging."""
    id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the auth event", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
    userId: str = Field(description="ID of the user this event belongs to", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True})
    eventType: str = Field(description="Type of authentication event (e.g., 'login', 'logout', 'token_refresh')", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True})
    timestamp: float = Field(default_factory=getUtcTimestamp, description="Unix timestamp when the event occurred", json_schema_extra={"frontend_type": "datetime", "frontend_readonly": True, "frontend_required": True})
    ipAddress: Optional[str] = Field(default=None, description="IP address from which the event originated", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
    userAgent: Optional[str] = Field(default=None, description="User agent string from the request", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
    success: bool = Field(default=True, description="Whether the authentication event was successful", json_schema_extra={"frontend_type": "boolean", "frontend_readonly": True, "frontend_required": True})
    details: Optional[str] = Field(default=None, description="Additional details about the event", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})


registerModelLabels(
    "AuthEvent",
    {"en": "Authentication Event", "de": "Authentifizierungsereignis", "fr": "Événement d'authentification"},
    {
        "id": {"en": "ID", "de": "ID", "fr": "ID"},
        "userId": {"en": "User ID", "de": "Benutzer-ID", "fr": "ID utilisateur"},
        "eventType": {"en": "Event Type", "de": "Ereignistyp", "fr": "Type d'événement"},
        "timestamp": {"en": "Timestamp", "de": "Zeitstempel", "fr": "Horodatage"},
        "ipAddress": {"en": "IP Address", "de": "IP-Adresse", "fr": "Adresse IP"},
        "userAgent": {"en": "User Agent", "de": "User-Agent", "fr": "Agent utilisateur"},
        "success": {"en": "Success", "de": "Erfolgreich", "fr": "Succès"},
        "details": {"en": "Details", "de": "Details", "fr": "Détails"},
    },
)
