"""Dispatch table mapping ``(office_code, right)`` → scraper coroutine.

Kept as an explicit dict (no decorator registry) because v1 has six
routes and a flat table is easier to read than dynamic registration.
New offices add one line per route here.
"""

from __future__ import annotations

from collections.abc import Awaitable, Callable

from .models import FeeSchedule, RightType
from .scrapers import cipo as _cipo
from .scrapers import cnipa as _cnipa
from .scrapers import dpma as _dpma
from .scrapers import epo as _epo
from .scrapers import euipo as _euipo
from .scrapers import hk_ipd as _hk_ipd
from .scrapers import ilpo as _ilpo
from .scrapers import impi as _impi
from .scrapers import inpi_br as _inpi_br
from .scrapers import inpi_fr as _inpi_fr
from .scrapers import ipaustralia as _ipau
from .scrapers import ipindia as _ipindia
from .scrapers import ipos as _ipos
from .scrapers import jpo as _jpo
from .scrapers import kipo as _kipo
from .scrapers import oepm as _oepm
from .scrapers import prh_fi as _prh_fi
from .scrapers import prv_se as _prv
from .scrapers import tipo as _tipo
from .scrapers import turkpatent as _turkpatent
from .scrapers import ukipo as _ukipo
from .scrapers import uspto as _uspto
from .scrapers import wipo as _wipo

# Each scraper takes no arguments; it owns its own BaseAsyncClient and
# closes it on exit. Returning a fully-validated FeeSchedule is the
# only contract.
Scraper = Callable[[], Awaitable[FeeSchedule]]


_DISPATCH: dict[tuple[str, RightType], Scraper] = {
    ("USPTO", RightType.patent): _uspto.scrape_uspto_patents,
    ("USPTO", RightType.trademark): _uspto.scrape_uspto_trademarks,
    ("USPTO", RightType.design): _uspto.scrape_uspto_designs,
    ("EPO", RightType.patent): _epo.scrape_epo_patents,
    ("EUIPO", RightType.trademark): _euipo.scrape_euipo_trademarks,
    ("EUIPO", RightType.design): _euipo.scrape_euipo_designs,
    ("CNIPA", RightType.patent): _cnipa.scrape_cnipa_patents,
    ("CIPO", RightType.patent): _cipo.scrape_cipo_patents,
    ("DPMA", RightType.patent): _dpma.scrape_dpma_patents,
    ("KIPO", RightType.patent): _kipo.scrape_kipo_patents,
    ("KIPO", RightType.trademark): _kipo.scrape_kipo_trademarks,
    ("KIPO", RightType.design): _kipo.scrape_kipo_designs,
    ("IPAU", RightType.patent): _ipau.scrape_ipaustralia_patents,
    ("UKIPO", RightType.patent): _ukipo.scrape_ukipo_patents,
    ("UKIPO", RightType.trademark): _ukipo.scrape_ukipo_trademarks,
    ("JPO", RightType.patent): _jpo.scrape_jpo_patents,
    ("JPO", RightType.trademark): _jpo.scrape_jpo_trademarks,
    ("JPO", RightType.design): _jpo.scrape_jpo_designs,
    ("IPIN", RightType.patent): _ipindia.scrape_ipindia_patents,
    ("TIPO", RightType.patent): _tipo.scrape_tipo_patents,
    ("TIPO", RightType.trademark): _tipo.scrape_tipo_trademarks,
    ("INPI-BR", RightType.patent): _inpi_br.scrape_inpi_br_patents,
    ("INPI-BR", RightType.trademark): _inpi_br.scrape_inpi_br_trademarks,
    ("INPI-FR", RightType.patent): _inpi_fr.scrape_inpi_fr_patents,
    ("INPI-FR", RightType.trademark): _inpi_fr.scrape_inpi_fr_trademarks,
    ("INPI-FR", RightType.design): _inpi_fr.scrape_inpi_fr_designs,
    ("OEPM", RightType.patent): _oepm.scrape_oepm_patents,
    ("OEPM", RightType.trademark): _oepm.scrape_oepm_trademarks,
    ("OEPM", RightType.design): _oepm.scrape_oepm_designs,
    ("HKIPD", RightType.patent): _hk_ipd.scrape_hk_patents,
    ("HKIPD", RightType.trademark): _hk_ipd.scrape_hk_trademarks,
    ("HKIPD", RightType.design): _hk_ipd.scrape_hk_designs,
    ("ILPO", RightType.patent): _ilpo.scrape_ilpo_patents,
    ("ILPO", RightType.trademark): _ilpo.scrape_ilpo_trademarks,
    ("ILPO", RightType.design): _ilpo.scrape_ilpo_designs,
    ("IMPI", RightType.patent): _impi.scrape_impi_patents,
    ("IMPI", RightType.trademark): _impi.scrape_impi_trademarks,
    ("IMPI", RightType.design): _impi.scrape_impi_designs,
    ("IPOS", RightType.patent): _ipos.scrape_ipos_patents,
    ("IPOS", RightType.trademark): _ipos.scrape_ipos_trademarks,
    ("IPOS", RightType.design): _ipos.scrape_ipos_designs,
    ("TURKPATENT", RightType.patent): _turkpatent.scrape_turkpatent_patents,
    ("TURKPATENT", RightType.trademark): _turkpatent.scrape_turkpatent_trademarks,
    ("TURKPATENT", RightType.design): _turkpatent.scrape_turkpatent_designs,
    ("PRH", RightType.patent): _prh_fi.scrape_prh_patents,
    ("PRH", RightType.trademark): _prh_fi.scrape_prh_trademarks,
    ("PRH", RightType.design): _prh_fi.scrape_prh_designs,
    ("PRV", RightType.patent): _prv.scrape_prv_patents,
    ("PRV", RightType.trademark): _prv.scrape_prv_trademarks,
    ("PRV", RightType.design): _prv.scrape_prv_designs,
    ("WIPO-PCT", RightType.patent): _wipo.scrape_wipo_pct,
    ("WIPO-MADRID", RightType.trademark): _wipo.scrape_wipo_madrid,
    ("WIPO-HAGUE", RightType.design): _wipo.scrape_wipo_hague,
}


OFFICES: tuple[str, ...] = (
    "USPTO",
    "EPO",
    "EUIPO",
    "CNIPA",
    "CIPO",
    "DPMA",
    "KIPO",
    "IPAU",
    "UKIPO",
    "JPO",
    "IPIN",
    "TIPO",
    "INPI-BR",
    "INPI-FR",
    "OEPM",
    "HKIPD",
    "ILPO",
    "IMPI",
    "IPOS",
    "TURKPATENT",
    "PRH",
    "PRV",
    "WIPO-PCT",
    "WIPO-MADRID",
    "WIPO-HAGUE",
)
"""Office codes covered in v1, in stable order for tool docstrings + listings."""


class UnsupportedRouteError(ValueError):
    """Raised when ``(office, right)`` has no registered scraper."""


def get_scraper(office_code: str, right: RightType) -> Scraper:
    """Look up the scraper for ``(office_code, right)``."""
    key = (office_code.upper(), right)
    try:
        return _DISPATCH[key]
    except KeyError as exc:
        raise UnsupportedRouteError(
            f"No fee scraper registered for office={office_code!r} "
            f"right={right.value!r}. Supported: {list_supported_routes()}."
        ) from exc


def list_supported_routes() -> list[tuple[str, str]]:
    """Return every ``(office_code, right_value)`` pair we can scrape."""
    return [(office, right.value) for (office, right) in _DISPATCH]


__all__ = [
    "OFFICES",
    "Scraper",
    "UnsupportedRouteError",
    "get_scraper",
    "list_supported_routes",
]
