"""Audit event Pydantic models.

Includes both authorization decision events and mutation events for
configuration changes (role/policy adds, removes, etc.).
"""

from datetime import datetime
from enum import StrEnum

from pydantic import BaseModel


class AuditEvent(BaseModel):
    """Structured audit event for an authorization decision.

    Captures the full context of a decision for compliance and debugging.

    The optional fields (source_ip, request_id, service_id) support NIST 800-53
    AU-3 (Content of Audit Records) requirements for federal environments.
    Existing code that doesn't set these fields continues to work unchanged.
    """

    timestamp: datetime
    decision: str  # "ALLOW" or "DENY"
    subject_id: str
    subject_roles: list[str]
    action: str
    resource_type: str
    resource_id: str
    matched_policies: list[str]
    reasoning: list[str]
    duration_us: int

    # Optional compliance fields (NIST 800-53 AU-3)
    source_ip: str | None = None
    request_id: str | None = None
    service_id: str | None = None


class MutationAction(StrEnum):
    """Types of configuration mutations that are audited."""

    ROLE_ADDED = "role_added"
    ROLE_REMOVED = "role_removed"
    ROLES_REPLACED = "roles_replaced"
    POLICY_ADDED = "policy_added"
    POLICY_REMOVED = "policy_removed"
    POLICIES_REPLACED = "policies_replaced"
    TEMPORAL_ROLE_ASSIGNED = "temporal_role_assigned"
    TEMPORAL_ROLE_REVOKED = "temporal_role_revoked"
    DELEGATION_CREATED = "delegation_created"
    DELEGATION_REVOKED = "delegation_revoked"


class MutationEvent(BaseModel):
    """Audit event for a configuration change.

    Tracks role, policy, temporal role, and delegation mutations for
    NIST 800-53 AC-2 (Account Management) and CM-3 (Configuration Change Control).

    Example:
        event = MutationEvent(
            mutation_action=MutationAction.ROLE_ADDED,
            target_name="admin",
            details={"permissions": ["*:*"]},
        )
    """

    timestamp: datetime
    mutation_action: MutationAction
    target_name: str
    details: dict = {}
    performed_by: str | None = None
    service_id: str | None = None
