"""Futures fetch: injected fake Databento client — per-root cost gate, cumulative cap, write path. No network."""
from __future__ import annotations

from fxhnt.adapters.data.futures_fetch import fetch_futures


class _FakeData:
    def __init__(self, n): self._n = n
    def to_file(self, path): open(path, "w").close()
    def __iter__(self): return iter(range(self._n))


class _FakeClient:
    """Mimics databento.Historical: .metadata.get_cost / .get_dataset_range, .timeseries.get_range."""
    def __init__(self, cost): self._cost = cost; self.metadata = self; self.timeseries = self
    def get_dataset_range(self, dataset): return {"end": "2026-06-13"}
    def get_cost(self, **kw): return self._cost
    def get_range(self, **kw): return _FakeData(100)


def test_fetches_within_caps(tmp_path) -> None:
    recs, ok, spent = fetch_futures(str(tmp_path), roots=["ES", "NQ"], start="2020-01-01", end="2026-06-30",
                                    max_cost_usd=40.0, per_root_cap_usd=10.0, client=_FakeClient(0.30))
    assert ok == 2 and recs == 200
    assert abs(spent - 0.60) < 1e-9
    assert (tmp_path / "ES.dbn").exists() and (tmp_path / "NQ.dbn").exists()


def test_per_root_cap_skips_expensive_root(tmp_path) -> None:
    recs, ok, spent = fetch_futures(str(tmp_path), roots=["ES"], start="2020-01-01", end="2026-06-30",
                                    max_cost_usd=40.0, per_root_cap_usd=0.10, client=_FakeClient(0.30))
    assert ok == 0 and recs == 0 and spent == 0.0       # 0.30 > 0.10 per-root cap -> skipped, no download
    assert not (tmp_path / "ES.dbn").exists()


def test_cumulative_cap_stops_further_roots(tmp_path) -> None:
    recs, ok, spent = fetch_futures(str(tmp_path), roots=["ES", "NQ", "YM"], start="2020-01-01",
                                    end="2026-06-30", max_cost_usd=0.50, per_root_cap_usd=10.0,
                                    client=_FakeClient(0.30))
    assert ok == 1 and abs(spent - 0.30) < 1e-9         # ES ok (0.30); NQ would breach 0.50 -> stop
