"""Unit of Work protocol for transaction management."""

from __future__ import annotations

from typing import TYPE_CHECKING, Protocol, Self, runtime_checkable

if TYPE_CHECKING:
    from .repositories import (
        AnnotationRepository,
        AssetRepository,
        DiarizationJobRepository,
        EntityRepository,
        IntegrationRepository,
        MeetingRepository,
        PreferencesRepository,
        SegmentRepository,
        SummaryRepository,
        UsageEventRepository,
        UserRepository,
        WebhookRepository,
        WorkspaceRepository,
    )
    from .repositories.identity import ProjectMembershipRepository, ProjectRepository


class UnitOfWorkCapabilities(Protocol):
    """Protocol for checking which features a UnitOfWork implementation supports.

    Memory-backed implementations may not support all features.
    Check these flags before accessing optional repositories.
    """

    @property
    def supports_annotations(self) -> bool:
        """Check if annotation operations are supported."""
        ...

    @property
    def supports_diarization_jobs(self) -> bool:
        """Check if diarization job persistence is supported."""
        ...

    @property
    def supports_preferences(self) -> bool:
        """Check if user preferences persistence is supported."""
        ...

    @property
    def supports_entities(self) -> bool:
        """Check if NER entity persistence is supported."""
        ...

    @property
    def supports_integrations(self) -> bool:
        """Check if OAuth integration persistence is supported."""
        ...

    @property
    def supports_webhooks(self) -> bool:
        """Check if webhook persistence is supported."""
        ...

    @property
    def supports_usage_events(self) -> bool:
        """Check if usage event persistence is supported."""
        ...

    @property
    def supports_users(self) -> bool:
        """Check if user persistence is supported."""
        ...

    @property
    def supports_workspaces(self) -> bool:
        """Check if workspace persistence is supported."""
        ...

    @property
    def supports_projects(self) -> bool:
        """Check if project persistence is supported."""
        ...


@runtime_checkable
class UnitOfWork(UnitOfWorkCapabilities, Protocol):
    """Unit of Work protocol for managing transactions across repositories.

    Provides transactional consistency when operating on multiple
    aggregates. Use as a context manager for automatic commit/rollback.

    Implementations may be backed by either a database (SqlAlchemyUnitOfWork)
    or in-memory storage (MemoryUnitOfWork). The `supports_*` properties
    indicate which features are available in the current implementation.

    Example:
        async with uow:
            meeting = await uow.meetings.get(meeting_id)
            await uow.segments.add(meeting_id, segment)
            await uow.commit()
    """

    # Core repositories (always available)
    @property
    def meetings(self) -> MeetingRepository:
        """Access the meetings repository."""
        ...

    @property
    def segments(self) -> SegmentRepository:
        """Access the segments repository."""
        ...

    @property
    def summaries(self) -> SummaryRepository:
        """Access the summaries repository."""
        ...

    @property
    def assets(self) -> AssetRepository:
        """Access the assets repository."""
        ...

    # Optional repositories (check supports_* before use)
    @property
    def annotations(self) -> AnnotationRepository:
        """Access the annotations repository."""
        ...

    @property
    def diarization_jobs(self) -> DiarizationJobRepository:
        """Access the diarization jobs repository."""
        ...

    @property
    def preferences(self) -> PreferencesRepository:
        """Access the preferences repository."""
        ...

    @property
    def entities(self) -> EntityRepository:
        """Access the entities repository for NER results."""
        ...

    @property
    def integrations(self) -> IntegrationRepository:
        """Access the integrations repository for OAuth connections."""
        ...

    @property
    def webhooks(self) -> WebhookRepository:
        """Access the webhooks repository for event notifications."""
        ...

    @property
    def usage_events(self) -> UsageEventRepository:
        """Access the usage events repository for analytics."""
        ...

    @property
    def users(self) -> UserRepository:
        """Access the users repository for identity management."""
        ...

    @property
    def workspaces(self) -> WorkspaceRepository:
        """Access the workspaces repository for tenancy management."""
        ...

    @property
    def projects(self) -> ProjectRepository:
        """Access the projects repository for project management."""
        ...

    @property
    def project_memberships(self) -> ProjectMembershipRepository:
        """Access the project memberships repository for access control."""
        ...

    # Lifecycle methods
    async def __aenter__(self) -> Self:
        """Enter the unit of work context.

        Returns:
            Self for use in async with statement.
        """
        ...

    async def __aexit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: object,
    ) -> None:
        """Exit the unit of work context.

        Rolls back on exception, otherwise commits.

        Args:
            exc_type: Exception type if raised.
            exc_val: Exception value if raised.
            exc_tb: Exception traceback if raised.
        """
        ...

    async def commit(self) -> None:
        """Commit the current transaction.

        Persists all changes made within the unit of work.
        """
        ...

    async def rollback(self) -> None:
        """Rollback the current transaction.

        Discards all changes made within the unit of work.
        """
        ...
