"""Adapter registry for the universal Fetch Data Toggle system.

Each adapter implements the :class:`SyncAdapter` protocol (3 coroutines:
``fetch_clients``, ``fetch_accounts``, ``fetch_domains``) and is
registered once, at import time, against a module key.

The engine looks adapters up by module_name, so admin endpoints remain
module-agnostic: adding a future reseller module only needs a new
adapter file + registration, no engine changes.
"""
from __future__ import annotations

from typing import Dict, List, Protocol

from sqlalchemy.ext.asyncio import AsyncSession

from services.module_sync.engine import SyncAttempt


class SyncAdapter(Protocol):
    """Protocol every per-module adapter must satisfy."""

    module_name: str
    module_label: str

    async def fetch_clients(self, db: AsyncSession) -> SyncAttempt: ...

    async def fetch_accounts(self, db: AsyncSession) -> SyncAttempt: ...

    async def fetch_domains(self, db: AsyncSession) -> SyncAttempt: ...


class _Registry:
    """In-memory registry of registered adapters, keyed by module_name."""

    def __init__(self) -> None:
        self._adapters: Dict[str, SyncAdapter] = {}

    def register(self, adapter: SyncAdapter) -> None:
        self._adapters[adapter.module_name] = adapter

    def get_adapter(self, module_name: str) -> SyncAdapter:
        if module_name not in self._adapters:
            raise KeyError(f"No sync adapter registered for module '{module_name}'")
        return self._adapters[module_name]

    def list_modules(self) -> List[str]:
        return sorted(self._adapters.keys())

    def list_adapters(self) -> List[SyncAdapter]:
        return [self._adapters[name] for name in self.list_modules()]


registry = _Registry()


# Register the built-in adapters at import time. Importing each module
# runs its `registry.register(...)` call.
from services.module_sync.adapters import uptimerobot as _ur  # noqa: E402,F401
from services.module_sync.adapters import bizmail360 as _bm  # noqa: E402,F401
from services.module_sync.adapters import whatsapp as _wa  # noqa: E402,F401
from services.module_sync.adapters import cpanel as _cp  # noqa: E402,F401