"""
Abstract base classes for AutoPIL storage backends.

All methods that touch stored data are scoped by tenant_id.
Swap backends by changing the concrete class — nothing else changes.
"""

from abc import ABC, abstractmethod

from autopil.models import AuditEvent


class AuditLogBase(ABC):

    @abstractmethod
    def record(self, event: AuditEvent, tenant_id: str = "default") -> None:
        """Persist an audit event. Append-only — no updates."""

    @abstractmethod
    def get_session_events(self, session_id: str, tenant_id: str = "default") -> list[AuditEvent]:
        """Return all events for a session scoped to tenant, ordered by timestamp."""

    @abstractmethod
    def get_all_events(self, tenant_id: str = "default") -> list[AuditEvent]:
        """Return all events for a tenant, ordered by timestamp."""

    @abstractmethod
    def get_session_owner(self, session_id: str, tenant_id: str = "default") -> str | None:
        """Return the agent_role that first recorded an event for this session."""


class KeyStoreBase(ABC):

    @abstractmethod
    def create_key(self, name: str, tenant_id: str, is_superadmin: bool = False) -> tuple[str, str]:
        """Create a key for a tenant. Returns (key_id, plaintext). Plaintext shown once."""

    @abstractmethod
    def validate(self, plaintext: str) -> dict | None:
        """
        Validate a plaintext key. Returns dict with key_id, tenant_id, is_superadmin,
        or None if invalid/revoked. Updates last_used timestamp.
        """

    @abstractmethod
    def list_keys(self, tenant_id: str) -> list[dict]:
        """Return all keys for a tenant. Never include plaintext or hash."""

    @abstractmethod
    def revoke(self, key_id: str, tenant_id: str) -> bool:
        """Revoke a key. Returns True if the key existed and belonged to this tenant."""

    @abstractmethod
    def count(self, tenant_id: str | None = None) -> int:
        """Total keys. Pass tenant_id to count for a specific tenant."""


class TenantStoreBase(ABC):

    @abstractmethod
    def create_tenant(self, name: str) -> str:
        """Create a tenant. Returns tenant_id."""

    @abstractmethod
    def get_tenant(self, tenant_id: str) -> dict | None:
        """Return tenant record or None."""

    @abstractmethod
    def list_tenants(self) -> list[dict]:
        """Return all tenants."""

    @abstractmethod
    def deactivate_tenant(self, tenant_id: str) -> bool:
        """Deactivate a tenant. Returns True if it existed."""

    @abstractmethod
    def count(self) -> int:
        """Total number of tenants."""


class PolicyStoreBase(ABC):

    @abstractmethod
    def upsert(self, policy: dict, tenant_id: str, changed_by: str | None = None) -> str:
        """Create or update a policy. Saves old version to history. Returns policy_id."""

    @abstractmethod
    def get(self, name: str, tenant_id: str) -> dict | None:
        """Return active policy by name, or None."""

    @abstractmethod
    def list_active(self, tenant_id: str) -> list[dict]:
        """Return all active policies for tenant, ordered by name."""

    @abstractmethod
    def delete(self, name: str, tenant_id: str) -> bool:
        """Soft-delete a policy. Returns True if it existed and was active."""

    @abstractmethod
    def get_history(self, name: str, tenant_id: str) -> list[dict]:
        """Return version history for a policy, newest first."""

    @abstractmethod
    def count(self, tenant_id: str) -> int:
        """Count active policies for a tenant."""
