"""Data source for the combined book — the A→B seam. The book reads its crypto panel + futures series
through this port; RawFileSource is the existing raw-file path, WarehouseSource reads the SSOT."""
from __future__ import annotations

from typing import Protocol

import numpy as np

from fxhnt.adapters.data.dbn_local import LocalDbnLoader
from fxhnt.adapters.warehouse.price_provider import WarehousePriceProvider
from fxhnt.application.crypto_momentum_research import _panel, load_crypto_panel
from fxhnt.domain.models import AssetClass, Market, PriceSeries
from fxhnt.ports.warehouse import FeatureStore


class CombinedBookSource(Protocol):
    def crypto_panel(self) -> tuple[list[int], list[str], np.ndarray, np.ndarray]:
        """(days, syms, close[d×s], ret[d×s]) — same shape as load_crypto_panel."""
        ...

    def futures_series(self, root: str) -> PriceSeries:
        """Continuous front-month PriceSeries for a futures root."""
        ...


class RawFileSource:
    def __init__(self, data_dir: str, crypto_subdir: str = "crypto_pit") -> None:
        self._dir = data_dir
        self._sub = crypto_subdir
        self._loader = LocalDbnLoader()

    def crypto_panel(self) -> tuple[list[int], list[str], np.ndarray, np.ndarray]:
        return load_crypto_panel(f"{self._dir}/{self._sub}")

    def futures_series(self, root: str) -> PriceSeries:
        return self._loader.load(f"{self._dir}/{root}.dbn", root)


class WarehouseSource:
    """Reads the combined book's data from the warehouse SSOT. Crypto = the panel of all USDT-perp
    symbols in the warehouse; futures = per-root continuous front via WarehousePriceProvider."""

    def __init__(self, store: FeatureStore) -> None:
        self._store = store
        self._provider = WarehousePriceProvider(store)

    def _crypto_symbols(self) -> list[str]:
        return [s for s, *_ in self._store.catalog() if s.endswith("USDT")]

    def crypto_panel(self) -> tuple[list[int], list[str], np.ndarray, np.ndarray]:
        data = self._store.read_panel(self._crypto_symbols(), "close")
        return _panel(data)

    def futures_series(self, root: str) -> PriceSeries:
        return self._provider.fetch(Market(symbol=root, asset_class=AssetClass.FUTURE))
