from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any


class AdapterError(RuntimeError):
    pass


class MarketAdapter(ABC):
    """Uniform adapter: probe / fetch / normalize. Realtime adapters may be stubs in P0."""

    name: str = "base"

    @abstractmethod
    def probe(self) -> dict[str, Any]:
        """Liveness check. Must not leak credentials."""

    @abstractmethod
    def fetch(self, dataset: str, params: dict[str, Any]) -> list[dict[str, Any]]:
        """Return provider-native rows (pre-canonical)."""

    @abstractmethod
    def normalize(self, dataset: str, rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
        """Map provider-native rows onto hub canonical fields."""


class ReservedAdapter(MarketAdapter):
    """Placeholder for a later free/licensed source. Does not pull data in P0."""

    def __init__(self, name: str) -> None:
        self.name = name

    def probe(self) -> dict[str, Any]:
        return {
            "provider": self.name,
            "configured": False,
            "state": "reserved",
            "message": "适配器位已预留，本阶段不接入",
        }

    def fetch(self, dataset: str, params: dict[str, Any]) -> list[dict[str, Any]]:
        raise AdapterError(f"{self.name} 适配器本阶段未接入")

    def normalize(self, dataset: str, rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
        return []
