"""The plain `build_bybit_paper_book` driver (the Dagster-free seam the `bybit_paper_book` asset calls):
persists the bybit live book via the venue repo and is READ-ONLY against the warehouse store. NO network."""
from __future__ import annotations

import datetime as dt

from fxhnt.adapters.orchestration.assets import build_bybit_paper_book
from fxhnt.adapters.persistence.paper_repo import PaperRepo
from fxhnt.adapters.warehouse.timescale_feature_store import TimescaleFeatureStore

_DAY = 86_400
_AT = dt.datetime(2026, 6, 24, 23, 30, tzinfo=dt.UTC)


def _seed(store: TimescaleFeatureStore, *, days: int = 200) -> list[dict]:
    import math as _m
    syms = ["BTCUSDT", "AAAUSDT", "BBBUSDT", "CCCUSDT"]
    px = {s: 100.0 for s in syms}
    px["BTCUSDT"] = 50_000.0
    for d in range(days):
        crowd = (d % 3 == 0)
        for s in syms:
            drift = {"BTCUSDT": 0.001, "AAAUSDT": 0.002, "BBBUSDT": -0.001, "CCCUSDT": 0.0015}[s]
            px[s] *= (1.0 + drift + 0.003 * _m.sin(d / 5.0 + hash(s) % 7))
            ratio = (0.70 if crowd else 0.30) if s == "AAAUSDT" else \
                    (0.30 if crowd else 0.70) if s == "BBBUSDT" else 0.50
            store.write_features(s, [(d * _DAY, {
                "close": px[s], "funding": 0.0005, "spot_close": px[s] * 1.0002, "long_ratio": ratio})])
    return [{"sym": "AAA", "cliff_day": days - 5, "n": 5_000_000.0, "cat": "insiders"}]


class _WriteTripwireStore:
    """Read-only proxy: ANY warehouse write/persist call trips an assertion (the asset must not write)."""

    _FORBIDDEN = frozenset({
        "write_features", "write_features_bulk", "upsert_feature_rows", "upsert_membership",
        "_create_schema", "_bulk_upsert",
    })

    def __init__(self, inner: TimescaleFeatureStore) -> None:
        object.__setattr__(self, "_inner", inner)

    def __getattr__(self, name: str):
        if name in _WriteTripwireStore._FORBIDDEN:
            raise AssertionError(f"READ-ONLY violation: bybit_paper_book called warehouse write {name!r}")
        return getattr(self._inner, name)


def test_driver_persists_and_is_read_only_against_warehouse() -> None:
    store = TimescaleFeatureStore("sqlite://", table="bybit_features")
    events = _seed(store)
    repo = PaperRepo("sqlite://")
    repo.migrate()
    n = build_bybit_paper_book(repo, _WriteTripwireStore(store), capital=100_000.0, at=_AT,
                               unlock_events=events, enabled=True)
    store.close()
    assert n > 0
    assert repo.latest_positions()
    assert repo.nav_history()
