"""`fxhnt compare-measured-precompute` — the OWN-MEMORY writer of the Bybit single-book measured-cost
artifacts.

The per-coin measured-cost compute used to run LIVE in the cockpit web handler and OOM-killed the 4Gi
`fxhnt-dashboard` pod (exit 137). The compute now runs only here (own-memory Job), persisting
`compare_measured_cache`. This asserts the CLI computes + upserts the artifacts and is idempotent.

(Phase 0b venue consolidation, Task 7b: the Binance combined-book leg + the Binance-vs-Bybit COMPARE
artifact this CLI used to also persist are retired — Bybit is fxhnt's sole crypto venue; the CLI now
persists ONLY the `bybit_4edge` (+ `bybit_4edge_levered`) single-book curves.)

NO network: the operational DSN points at a temp sqlite db; the `bybit_features` warehouse + cockpit tables
are seeded on it directly.
"""
from __future__ import annotations

import datetime as dt

from typer.testing import CliRunner

from fxhnt.cli import app

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


def _seed(dsn: str) -> None:
    """Seed a wide-spread Bybit `xsfunding` carry universe + sleeve returns on `bybit_features` — the
    inputs the precompute reads."""
    from fxhnt.adapters.warehouse.timescale_feature_store import TimescaleFeatureStore

    store = TimescaleFeatureStore(dsn, table="bybit_features")
    start = dt.date(2021, 1, 1)
    days = 60
    funding = {"AAAUSDT": 0.001, "BBBUSDT": 0.001, "XXXUSDT": -0.001, "YYYUSDT": -0.001}
    for idx, (sym, fund) in enumerate(funding.items()):
        rows = []
        for d in range(days):
            f = fund + 0.0005 * ((d + idx) % 3 - 1)
            half = 0.01  # 200bp wide spread
            ts = (start + dt.timedelta(days=d)).toordinal() * _DAY
            rows.append((ts, {"funding": f, "close": 100.0, "spot_close": 100.0,
                              "high": 100.0 * (1 + half), "low": 100.0 * (1 - half),
                              "turnover": 50_000_000.0}))
        store.write_features(sym, rows)
    store.close()


def _patch(monkeypatch, tmp_path) -> str:
    dsn = f"sqlite:///{tmp_path / 'op.db'}"
    monkeypatch.setenv("FXHNT_OPERATIONAL_DSN", dsn)
    from fxhnt import cli as climod
    climod.get_settings.cache_clear()
    _seed(dsn)
    return dsn


def test_cli_persists_single_book_cache(monkeypatch, tmp_path) -> None:
    dsn = _patch(monkeypatch, tmp_path)
    res = CliRunner().invoke(app, ["compare-measured-precompute", "--capital", "100000"])
    assert res.exit_code == 0, res.output
    assert "persisted" in res.output.lower()

    from fxhnt.adapters.persistence.paper_repo import PaperRepo
    from fxhnt.application.compare_measured_cost import read_cached_single_measured
    payload = read_cached_single_measured(PaperRepo(dsn), "bybit_4edge")
    assert payload is not None
    assert payload["book"] == "bybit_4edge"
    assert payload["dates_iso"] and payload["equity"]


def test_cli_is_idempotent(monkeypatch, tmp_path) -> None:
    dsn = _patch(monkeypatch, tmp_path)
    runner = CliRunner()
    r1 = runner.invoke(app, ["compare-measured-precompute", "--capital", "100000"])
    assert r1.exit_code == 0, r1.output
    from fxhnt.adapters.persistence.paper_repo import PaperRepo
    from fxhnt.application.compare_measured_cost import read_cached_single_measured
    first = read_cached_single_measured(PaperRepo(dsn), "bybit_4edge")

    r2 = runner.invoke(app, ["compare-measured-precompute", "--capital", "100000"])
    assert r2.exit_code == 0, r2.output
    second = read_cached_single_measured(PaperRepo(dsn), "bybit_4edge")
    assert first is not None and second is not None
    assert first["equity"] == second["equity"]
