"""FXHNT_WAREHOUSE_TABLE knob: a single config flag selects WHICH warehouse table the feature store
reads/writes — the default `features` (Binance) vs `bybit_features` (Bybit) — so all edges
(tstrend/unlock/stablecoin/xsfunding) run on Bybit data by flipping the flag, with NO per-sleeve change.

The default is unchanged (`features`); the knob is opt-in via env (`FXHNT_WAREHOUSE_TABLE=bybit_features`).
We stand in for live Timescale with an in-memory sqlite DSN, the same drop-in store the parity tests use.
"""
from __future__ import annotations

from fxhnt.adapters.warehouse import TimescaleFeatureStore, get_feature_store
from fxhnt.config import Settings


def _pg_settings(*, warehouse_table: str | None = None) -> Settings:
    kw: dict = {"feature_store": "postgres", "operational_dsn": "sqlite://"}
    if warehouse_table is not None:
        kw["warehouse_table"] = warehouse_table
    return Settings(**kw)


def test_default_setting_is_features() -> None:
    """The default warehouse_table is the Binance `features` table — live behavior preserved."""
    assert Settings().warehouse_table == "features"


def test_env_overrides_warehouse_table(monkeypatch) -> None:
    """FXHNT_WAREHOUSE_TABLE drives the setting (env_prefix=FXHNT_)."""
    monkeypatch.setenv("FXHNT_WAREHOUSE_TABLE", "bybit_features")
    assert Settings().warehouse_table == "bybit_features"


def test_factory_default_table_is_features() -> None:
    store = get_feature_store(_pg_settings())
    assert isinstance(store, TimescaleFeatureStore)
    assert store._table == "features"


def test_factory_routes_to_bybit_table_when_set() -> None:
    store = get_feature_store(_pg_settings(warehouse_table="bybit_features"))
    assert isinstance(store, TimescaleFeatureStore)
    assert store._table == "bybit_features"


def test_book_sim_path_reads_configured_table() -> None:
    """A book/sim read (crypto_funding_panel) honors the knob: with two stores over the SAME engine — one
    on `features`, one on `bybit_features` — seeded with DIFFERENT funding, the factory-selected store
    returns the data of the configured table, so the resulting panel differs by flag value alone."""
    dsn = "sqlite://"
    # Two stores over the SAME in-memory engine would each get a private connection; instead, seed each
    # table via its own store but on DISTINCT engines, then assert the factory (which builds its own store
    # from the DSN) reads the table the setting names. To keep both tables in ONE engine, seed through a
    # single store per table sharing the StaticPool by reusing the same DSN object identity is not possible
    # for `sqlite://` (each create_engine gets a fresh :memory:). So seed a file-backed sqlite DB instead.
    import tempfile, os
    fd, path = tempfile.mkstemp(suffix=".db")
    os.close(fd)
    try:
        file_dsn = f"sqlite:///{path}"
        binance = TimescaleFeatureStore(file_dsn, table="features")
        bybit = TimescaleFeatureStore(file_dsn, table="bybit_features")
        # Same symbol + epoch_day, DIFFERENT funding values per table.
        ts = 86_400 * 100
        binance.write_features("BTCUSDT", [(ts, {"funding": 0.01})])
        bybit.write_features("BTCUSDT", [(ts, {"funding": 0.09})])

        s_default = Settings(feature_store="postgres", operational_dsn=file_dsn)
        s_bybit = Settings(feature_store="postgres", operational_dsn=file_dsn,
                           warehouse_table="bybit_features")

        panel_default = get_feature_store(s_default).crypto_funding_panel()
        panel_bybit = get_feature_store(s_bybit).crypto_funding_panel()

        assert panel_default["BTCUSDT"][100] == 0.01      # Binance table
        assert panel_bybit["BTCUSDT"][100] == 0.09        # Bybit table
        assert panel_default != panel_bybit               # the knob changed the data the sleeve sees
    finally:
        os.unlink(path)
