"""Warehouse contracts — the gold-layer feature store of the SSOT architecture.

Point-in-time by construction: features are keyed by (symbol, ts), and an `as_of(ts)` read returns only
features known at-or-before ts — no lookahead can leak into research. This is the discipline the analyst
agents stand on; a single as-of bug would silently poison every conclusion built above it.
"""
from __future__ import annotations

from typing import Protocol

FeatureRow = tuple[int, dict[str, float]]   # (ts, {feature_name: value})


class FeatureStore(Protocol):
    def write_features(self, symbol: str, rows: list[FeatureRow]) -> None:
        """Persist point-in-time feature rows for a symbol (idempotent on (symbol, ts, feature))."""
        ...

    def write_features_bulk(self, items: list[tuple[str, list[FeatureRow]]]) -> None:
        """Persist many symbols' feature rows in ONE transaction (bulk-ingest fast path); per-symbol
        idempotent. Equivalent result to calling write_features per symbol."""
        ...

    def read_features(self, symbol: str, *, start_ts: int | None = None, end_ts: int | None = None,
                      features: list[str] | None = None) -> list[FeatureRow]:
        """Read feature rows in [start_ts, end_ts], ordered by ts."""
        ...

    def as_of(self, symbol: str, ts: int, features: list[str] | None = None) -> dict[str, float]:
        """The latest feature values known at-or-before ts (no lookahead)."""
        ...

    def catalog(self) -> list[tuple[str, int, int, int]]:
        """Per symbol: (symbol, bar_count, first_ts, last_ts) over the 'close' feature."""
        ...

    def read_panel(self, symbols: list[str], feature: str) -> dict[str, dict[int, float]]:
        """{symbol: {epoch_day: value}} for one feature across symbols."""
        ...
