"""Persistence-backed audit store adapter.

Connects the existing AuditEventHandler with the new
persistent IAuditRepository implementation.
"""

import asyncio
from datetime import datetime, timezone
from typing import List, Optional

from ...domain.contracts.persistence import (
    AuditAction,
    AuditEntry,
    IAuditRepository,
)
from ...infrastructure.async_executor import submit_async
from ...logging_config import get_logger
from .audit_handler import AuditRecord, AuditStore

logger = get_logger(__name__)


class PersistentAuditStore(AuditStore):
    """Audit store backed by IAuditRepository.

    Bridges the synchronous AuditEventHandler with the
    async IAuditRepository for persistent storage.

    Uses AsyncExecutor for efficient background persistence
    without blocking the main thread.
    """

    def __init__(self, repository: IAuditRepository):
        """Initialize with audit repository.

        Args:
            repository: Async audit repository for persistence
        """
        self._repo = repository

    def record(self, audit_record: AuditRecord) -> None:
        """Store an audit record asynchronously.

        Converts AuditRecord to AuditEntry and persists using
        background executor.

        Args:
            audit_record: Record to store
        """
        entry = self._record_to_entry(audit_record)

        submit_async(self._async_record(entry), on_error=lambda e: logger.error(f"Failed to persist audit record: {e}"))

    async def _async_record(self, entry: AuditEntry) -> None:
        """Async record method."""
        try:
            await self._repo.append(entry)
        except Exception as e:
            logger.error(f"Failed to persist audit entry: {e}")

    def query(
        self,
        provider_id: Optional[str] = None,
        event_type: Optional[str] = None,
        since: Optional[datetime] = None,
        limit: int = 100,
    ) -> List[AuditRecord]:
        """Query audit records.

        Args:
            provider_id: Filter by provider ID
            event_type: Filter by event type (entity_type in new model)
            since: Filter records after this time
            limit: Maximum records to return

        Returns:
            List of audit records
        """
        try:
            if provider_id:
                coro = self._repo.get_by_entity(
                    entity_id=provider_id,
                    entity_type="provider",
                    limit=limit,
                )
            elif since:
                coro = self._repo.get_by_time_range(
                    start=since,
                    end=datetime.now(timezone.utc),
                    entity_type=event_type,
                    limit=limit,
                )
            else:
                # Get recent entries
                coro = self._repo.get_by_time_range(
                    start=datetime(2000, 1, 1, tzinfo=timezone.utc),
                    end=datetime.now(timezone.utc),
                    entity_type=event_type,
                    limit=limit,
                )

            # Check if we're in an async context
            try:
                asyncio.get_running_loop()
                # We're in async context - can't run sync query
                logger.warning("Cannot query audit in async context synchronously")
                return []
            except RuntimeError:
                # Not in async context - safe to use asyncio.run()
                entries = asyncio.run(coro)
                return [self._entry_to_record(e) for e in entries]

        except Exception as e:
            logger.error(f"Failed to query audit records: {e}")
            return []

    def _record_to_entry(self, record: AuditRecord) -> AuditEntry:
        """Convert AuditRecord to AuditEntry.

        Args:
            record: Legacy audit record

        Returns:
            New AuditEntry format
        """
        # Map event type to action
        action = self._map_event_to_action(record.event_type)

        # Handle timestamp
        if isinstance(record.occurred_at, datetime):
            timestamp = record.occurred_at
        elif isinstance(record.occurred_at, (int, float)):
            timestamp = datetime.fromtimestamp(record.occurred_at, tz=timezone.utc)
        else:
            timestamp = datetime.now(timezone.utc)

        return AuditEntry(
            entity_id=record.provider_id or "_unknown",
            entity_type="provider",
            action=action,
            timestamp=timestamp,
            actor="system",
            metadata={
                "event_id": record.event_id,
                "event_type": record.event_type,
                "data": record.data,
            },
        )

    def _entry_to_record(self, entry: AuditEntry) -> AuditRecord:
        """Convert AuditEntry to AuditRecord.

        Args:
            entry: New audit entry

        Returns:
            Legacy AuditRecord format
        """
        event_id = entry.metadata.get("event_id", str(entry.timestamp.timestamp()))
        event_type = entry.metadata.get("event_type", entry.action.value)
        data = entry.metadata.get("data", {})

        return AuditRecord(
            event_id=event_id,
            event_type=event_type,
            occurred_at=entry.timestamp,
            provider_id=entry.entity_id if entry.entity_id != "_unknown" else None,
            data=data,
            recorded_at=entry.timestamp,
        )

    def _map_event_to_action(self, event_type: str) -> AuditAction:
        """Map domain event type to audit action.

        Args:
            event_type: Domain event class name

        Returns:
            Corresponding AuditAction
        """
        mapping = {
            "ProviderStarted": AuditAction.STARTED,
            "ProviderStopped": AuditAction.STOPPED,
            "ProviderDegraded": AuditAction.DEGRADED,
            "ProviderStateChanged": AuditAction.STATE_CHANGED,
            "ProviderRegistered": AuditAction.CREATED,
            "ProviderUnregistered": AuditAction.DELETED,
            "ToolInvocationCompleted": AuditAction.UPDATED,
            "ToolInvocationFailed": AuditAction.STATE_CHANGED,
            "HealthCheckPassed": AuditAction.RECOVERED,
            "HealthCheckFailed": AuditAction.DEGRADED,
        }
        return mapping.get(event_type, AuditAction.UPDATED)


def create_persistent_audit_handler(
    repository: IAuditRepository,
    include_event_types: Optional[List[str]] = None,
    exclude_event_types: Optional[List[str]] = None,
):
    """Create AuditEventHandler with persistent storage.

    Factory function to create an AuditEventHandler backed
    by an IAuditRepository for durable storage.

    Args:
        repository: Audit repository for persistence
        include_event_types: Only record these event types
        exclude_event_types: Exclude these event types

    Returns:
        Configured AuditEventHandler
    """
    from .audit_handler import AuditEventHandler

    store = PersistentAuditStore(repository)
    return AuditEventHandler(
        store=store,
        include_event_types=include_event_types,
        exclude_event_types=exclude_event_types,
    )
