"""Feature pipeline → warehouse: persistence roundtrip + point-in-time as_of (no lookahead)."""
from __future__ import annotations

from fxhnt.adapters.warehouse import DuckDbFeatureStore
from fxhnt.application.feature_pipeline import FeaturePipeline
from fxhnt.domain.features import MicropriceFeatures
from fxhnt.domain.marketdata import BidAskLevel, Mbp10Snapshot

_BID, _ASK = 100_000_000_000, 100_040_000_000


def _snap(ts: int, bid_sz: int, ask_sz: int) -> Mbp10Snapshot:
    return Mbp10Snapshot(symbol="ES", ts=ts,
                         levels=(BidAskLevel(bid_px=_BID, bid_sz=bid_sz, ask_px=_ASK, ask_sz=ask_sz),))


def test_pipeline_persists_and_as_of_has_no_lookahead(tmp_path) -> None:
    store = DuckDbFeatureStore(str(tmp_path / "wh.duckdb"))
    pipeline = FeaturePipeline(store, [MicropriceFeatures()])

    n = pipeline.process("ES", [_snap(10, 1000, 10), _snap(20, 100, 100), _snap(30, 10, 1000)])
    assert n == 3

    rows = store.read_features("ES")
    assert [ts for ts, _ in rows] == [10, 20, 30]
    assert "stoikov_microprice" in rows[0][1]

    # as_of(25) must return the ts=20 state (the latest known), never the future ts=30
    at_25 = store.as_of("ES", 25)
    assert at_25 == rows[1][1]                                              # exactly the ts=20 state
    assert at_25["stoikov_microprice"] != rows[2][1]["stoikov_microprice"]  # ts=30 (heavy ask) NOT leaked
    assert rows[2][1]["microprice_residual_sign"] == -1.0                   # ts=30 is heavy-ask (residual < 0)
    assert store.as_of("ES", 5) == {}                                       # nothing known before the first bar
