"""In-memory integration repository implementation."""

from __future__ import annotations

from collections.abc import Sequence
from uuid import UUID

from noteflow.domain.entities.integration import Integration, SyncRun


class InMemoryIntegrationRepository:
    """In-memory integration repository for testing.

    Provide a functional integration repository backed by dictionaries
    for use in tests and memory mode.
    """

    def __init__(self) -> None:
        """Initialize with empty storage."""
        self._integrations: dict[UUID, Integration] = {}
        self._secrets: dict[UUID, dict[str, str]] = {}
        self._sync_runs: dict[UUID, SyncRun] = {}

    async def get(self, integration_id: UUID) -> Integration | None:
        """Retrieve an integration by ID."""
        return self._integrations.get(integration_id)

    async def get_by_provider(
        self,
        provider: str,
        integration_type: str | None = None,
    ) -> Integration | None:
        """Retrieve an integration by provider name."""
        for integration in self._integrations.values():
            provider_match = (
                integration.config.get("provider") == provider
                or provider.lower() in integration.name.lower()
            )
            type_match = integration_type is None or integration.type.value == integration_type
            if provider_match and type_match:
                return integration
        return None

    async def create(self, integration: Integration) -> Integration:
        """Persist a new integration."""
        self._integrations[integration.id] = integration
        return integration

    async def update(self, integration: Integration) -> Integration:
        """Update an existing integration."""
        if integration.id not in self._integrations:
            msg = f"Integration {integration.id} not found"
            raise ValueError(msg)
        self._integrations[integration.id] = integration
        return integration

    async def delete(self, integration_id: UUID) -> bool:
        """Delete an integration and its secrets."""
        if integration_id not in self._integrations:
            return False
        del self._integrations[integration_id]
        self._secrets.pop(integration_id, None)
        return True

    async def get_secrets(self, integration_id: UUID) -> dict[str, str] | None:
        """Get secrets for an integration."""
        if integration_id not in self._integrations:
            return None
        return self._secrets.get(integration_id, {})

    async def set_secrets(self, integration_id: UUID, secrets: dict[str, str]) -> None:
        """Store secrets for an integration."""
        self._secrets[integration_id] = secrets

    async def list_by_type(self, integration_type: str) -> Sequence[Integration]:
        """List integrations by type."""
        return [i for i in self._integrations.values() if i.type.value == integration_type]

    async def list_all(self) -> Sequence[Integration]:
        """List all integrations."""
        return list(self._integrations.values())

    async def create_sync_run(self, sync_run: SyncRun) -> SyncRun:
        """Persist a new sync run record.

        Args:
            sync_run: The SyncRun domain entity to persist.

        Returns:
            The persisted SyncRun entity.
        """
        self._sync_runs[sync_run.id] = sync_run
        return sync_run

    async def get_sync_run(self, sync_run_id: UUID) -> SyncRun | None:
        """Retrieve a sync run by ID.

        Args:
            sync_run_id: UUID of the sync run.

        Returns:
            The SyncRun entity if found, None otherwise.
        """
        return self._sync_runs.get(sync_run_id)

    async def update_sync_run(self, sync_run: SyncRun) -> SyncRun:
        """Update an existing sync run record.

        Args:
            sync_run: The SyncRun entity with updated state.

        Returns:
            The updated SyncRun entity.
        """
        self._sync_runs[sync_run.id] = sync_run
        return sync_run

    async def list_sync_runs(
        self,
        integration_id: UUID,
        limit: int = 20,
        offset: int = 0,
    ) -> tuple[Sequence[SyncRun], int]:
        """List sync runs for an integration with pagination.

        Args:
            integration_id: UUID of the integration.
            limit: Maximum runs to return.
            offset: Number of runs to skip.

        Returns:
            Tuple of (SyncRun entities newest first, total count).
        """
        runs = [r for r in self._sync_runs.values() if r.integration_id == integration_id]
        total = len(runs)
        # Sort by started_at descending
        runs.sort(key=lambda x: x.started_at, reverse=True)
        return runs[offset : offset + limit], total
