"""B3b: the `backtest-equity` CLI entrypoint runs the walk-forward equity backtest against the
DEDICATED backtest warehouse (settings.backtest_warehouse_path), evaluates the 3 price-only
constructions through the gauntlet, and writes a JSON report. No network: a synthetic warehouse
is built and the command is pointed at it via FXHNT_BACKTEST_WAREHOUSE_PATH."""
from __future__ import annotations

import datetime as dt
import json

from typer.testing import CliRunner

from fxhnt.adapters.warehouse.duckdb_feature_store import DuckDbFeatureStore

_SPD = 86_400


def _build_warehouse(path: str) -> DuckDbFeatureStore:
    """3 names over ~2 years of daily bars (mirrors the runner integration test): AAA strong uptrend,
    BBB mild, CCC downtrend — a non-degenerate cross-section for long/ls/tilt."""
    store = DuckDbFeatureStore(path)
    start = dt.date(2022, 1, 3)
    n = 520  # ~2 trading years
    drifts = {"AAA": 0.0015, "BBB": 0.0003, "CCC": -0.0010}
    items = []
    members = []
    for sym, dr in drifts.items():
        rows = []
        px = 100.0
        for i in range(n):
            day = start + dt.timedelta(days=i)
            px *= (1.0 + dr)
            ts = (day - dt.date(1970, 1, 1)).days * _SPD
            rows.append((ts, {"adjclose": px, "close": px, "volume": 1_000_000.0}))
        items.append((sym, rows))
        members.append((sym, "NYSE", "2000-01-01", "2026-06-01"))
    store.write_features_bulk(items)
    store.upsert_membership(members)
    return store


def test_cli_backtest_equity_writes_report(tmp_path, monkeypatch) -> None:
    import fxhnt.cli as cli

    wh = str(tmp_path / "wh.duckdb")
    _build_warehouse(wh).close()
    out = tmp_path / "report.json"

    monkeypatch.setenv("FXHNT_BACKTEST_WAREHOUSE_PATH", wh)
    cli.get_settings.cache_clear()  # settings are lru_cached — pick up the env override
    res = CliRunner().invoke(cli.app, ["backtest-equity", "--n", "10", "--out", str(out)])
    cli.get_settings.cache_clear()

    assert res.exit_code == 0, res.output
    assert out.exists(), "backtest-equity must write the report JSON at --out"
    report = json.loads(out.read_text())
    assert set(report["constructions"]) == {"long", "ls", "tilt"}
    for block in report["constructions"].values():
        assert {"stats", "verdict"} <= set(block)
        assert {"passed", "dsr", "is_sharpe", "oos_sharpe"} <= set(block["verdict"])


def test_cli_backtest_equity_bounded_candidate_flags(tmp_path, monkeypatch) -> None:
    """The bounded memory pre-filter flags (--candidate-top-k / --candidate-min-history) are exposed
    and passed to the runner; with thresholds the 3 synthetic names qualify -> full report."""
    import fxhnt.cli as cli

    wh = str(tmp_path / "wh.duckdb")
    _build_warehouse(wh).close()
    out = tmp_path / "report.json"

    monkeypatch.setenv("FXHNT_BACKTEST_WAREHOUSE_PATH", wh)
    cli.get_settings.cache_clear()  # settings are lru_cached — pick up the env override
    res = CliRunner().invoke(
        cli.app,
        [
            "backtest-equity", "--n", "10", "--out", str(out),
            "--candidate-top-k", "100", "--candidate-min-history", "10",
        ],
    )
    cli.get_settings.cache_clear()

    assert res.exit_code == 0, res.output
    assert out.exists(), "backtest-equity must write the report JSON at --out"
    report = json.loads(out.read_text())
    assert set(report["constructions"]) == {"long", "ls", "tilt"}
