"""
Audit log service helper for DocuVault — Phase 4.

Provides write_audit_log(), a fire-and-forget helper called inline by API
handlers after successful operations (D-14).

Key architectural constraints:
  - Uses session.flush() NOT session.commit() (D-14: the caller owns the
    transaction; the audit entry is flushed within the same transaction but
    the commit remains the caller's responsibility).
  - NEVER raises — audit failure must not abort the primary operation.
    Exceptions are logged at WARNING level and silently swallowed.
"""
from __future__ import annotations

import logging
import uuid
from typing import Optional

from sqlalchemy.ext.asyncio import AsyncSession

from db.models import AuditLog

logger = logging.getLogger(__name__)


async def write_audit_log(
    session: AsyncSession,
    event_type: str,
    user_id: Optional[uuid.UUID],
    actor_id: Optional[uuid.UUID],
    resource_id: Optional[uuid.UUID],
    ip_address: Optional[str],
    metadata_: Optional[dict] = None,
) -> None:
    """Write an audit log entry within the caller's transaction.

    Never raises — audit failure is non-fatal. Exceptions are caught and
    logged as warnings so the primary operation is never aborted.

    Uses session.flush() not session.commit() (D-14). The caller is responsible
    for committing the transaction; this function merely ensures the audit row
    is queued in the same unit of work.
    """
    try:
        entry = AuditLog(
            event_type=event_type,
            user_id=user_id,
            actor_id=actor_id,
            resource_id=resource_id,
            ip_address=ip_address,
            metadata_=metadata_,
        )
        session.add(entry)
        await session.flush()  # flush within handler's existing transaction, not commit
    except Exception as exc:
        logger.warning("audit log write failed: %s", exc)
        # Do not re-raise — audit failure must never abort the primary operation
