"""In-memory Unit of Work implementation.

Provides a UnitOfWork implementation backed by the MeetingStore for use
when no database is configured. Implements the same interface as
SqlAlchemyUnitOfWork for uniform access.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Self

from noteflow.domain.ports.repositories import (
    AnnotationRepository,
    AssetRepository,
    DiarizationJobRepository,
    EntityRepository,
    IntegrationRepository,
    MeetingRepository,
    PreferencesRepository,
    ProjectMembershipRepository,
    ProjectRepository,
    SegmentRepository,
    SummaryRepository,
    UsageEventRepository,
    UserRepository,
    WebhookRepository,
    WorkspaceRepository,
)

from .repositories import (
    InMemoryWebhookRepository,
    MemoryAssetRepository,
    MemoryMeetingRepository,
    MemorySegmentRepository,
    MemorySummaryRepository,
    UnsupportedAnnotationRepository,
    UnsupportedDiarizationJobRepository,
    UnsupportedEntityRepository,
    UnsupportedPreferencesRepository,
    UnsupportedProjectMembershipRepository,
    UnsupportedProjectRepository,
    UnsupportedUsageEventRepository,
    UnsupportedUserRepository,
    UnsupportedWorkspaceRepository,
)

if TYPE_CHECKING:
    from noteflow.grpc.meeting_store import MeetingStore


class MemoryUnitOfWork:
    """In-memory Unit of Work backed by MeetingStore.

    Implements the same interface as SqlAlchemyUnitOfWork for uniform
    access across database and memory backends.

    Commit and rollback are no-ops since changes are applied directly
    to the in-memory store.

    Example:
        async with MemoryUnitOfWork(store) as uow:
            meeting = await uow.meetings.get(meeting_id)
            await uow.segments.add(meeting_id, segment)
            await uow.commit()  # No-op, changes already applied
    """

    def __init__(self, store: MeetingStore) -> None:
        """Initialize unit of work with meeting store.

        Args:
            store: In-memory meeting storage.
        """
        self._store = store
        self._meetings = MemoryMeetingRepository(store)
        self._segments = MemorySegmentRepository(store)
        self._summaries = MemorySummaryRepository(store)
        self._annotations = UnsupportedAnnotationRepository()
        self._diarization_jobs = UnsupportedDiarizationJobRepository()
        self._preferences = UnsupportedPreferencesRepository()
        self._entities = UnsupportedEntityRepository()
        # Use shared integration repository from store for cross-UoW persistence
        self._integrations = store.integrations
        self._webhooks = InMemoryWebhookRepository()
        self._assets = MemoryAssetRepository()
        self._users = UnsupportedUserRepository()
        self._workspaces = UnsupportedWorkspaceRepository()
        self._usage_events = UnsupportedUsageEventRepository()
        self._projects = UnsupportedProjectRepository()
        self._project_memberships = UnsupportedProjectMembershipRepository()

    # Core repositories
    @property
    def meetings(self) -> MeetingRepository:
        """Get meetings repository."""
        return self._meetings

    @property
    def segments(self) -> SegmentRepository:
        """Get segments repository."""
        return self._segments

    @property
    def summaries(self) -> SummaryRepository:
        """Get summaries repository."""
        return self._summaries

    @property
    def assets(self) -> AssetRepository:
        """Get assets repository."""
        return self._assets

    # Optional repositories (unsupported in memory mode)
    @property
    def annotations(self) -> AnnotationRepository:
        """Get annotations repository (unsupported)."""
        return self._annotations

    @property
    def diarization_jobs(self) -> DiarizationJobRepository:
        """Get diarization jobs repository (unsupported)."""
        return self._diarization_jobs

    @property
    def preferences(self) -> PreferencesRepository:
        """Get preferences repository (unsupported)."""
        return self._preferences

    @property
    def entities(self) -> EntityRepository:
        """Get entities repository (unsupported)."""
        return self._entities

    @property
    def integrations(self) -> IntegrationRepository:
        """Get integrations repository."""
        return self._integrations

    @property
    def webhooks(self) -> WebhookRepository:
        """Get webhooks repository for event notifications."""
        return self._webhooks

    @property
    def usage_events(self) -> UsageEventRepository:
        """Get usage events repository (unsupported)."""
        return self._usage_events

    @property
    def users(self) -> UserRepository:
        """Get users repository (unsupported)."""
        return self._users

    @property
    def workspaces(self) -> WorkspaceRepository:
        """Get workspaces repository (unsupported)."""
        return self._workspaces

    @property
    def projects(self) -> ProjectRepository:
        """Get projects repository (unsupported)."""
        return self._projects

    @property
    def project_memberships(self) -> ProjectMembershipRepository:
        """Get project memberships repository (unsupported)."""
        return self._project_memberships

    # Feature capability flags - limited in memory mode
    supports_annotations: bool = False
    supports_diarization_jobs: bool = False
    supports_preferences: bool = False
    supports_entities: bool = False
    supports_integrations: bool = True
    supports_webhooks: bool = True
    supports_users: bool = False
    supports_workspaces: bool = False
    supports_usage_events: bool = False
    supports_projects: bool = False

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

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

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

        No-op for memory implementation since changes are applied directly.
        """

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

        No-op for memory implementation - changes are applied directly.
        """

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

        Note: Memory implementation does not support rollback.
        Changes are applied directly and cannot be undone.
        """
