"""B3a-deploy: the `ingest-historical` CLI entrypoint wires the historical-EOD ingest against the
DEDICATED backtest warehouse path (never the live cockpit warehouse) and honors --limit. No network:
the Tiingo clients are monkeypatched with fakes."""
from __future__ import annotations

from typer.testing import CliRunner

from fxhnt.config import Settings


def test_settings_has_backtest_warehouse_path_default() -> None:
    s = Settings()
    assert s.backtest_warehouse_path == "/backtest-data/warehouse.duckdb"


def test_settings_backtest_path_env_override(monkeypatch) -> None:
    monkeypatch.setenv("FXHNT_BACKTEST_WAREHOUSE_PATH", "/tmp/bt.duckdb")
    s = Settings()
    assert s.backtest_warehouse_path == "/tmp/bt.duckdb"


class _FakeUniverse:
    """Survivorship-free set: three members; .survivorship_free() returns (sym, exch, start, end)."""

    def survivorship_free(self):
        return [
            ("AAA", "NYSE", "1990-01-02", "2026-06-01"),
            ("BBB", "NASDAQ", "1995-03-01", "2010-12-31"),
            ("CCC", "AMEX", "2000-06-15", "2026-06-01"),
        ]


class _FakeBars:
    def bars(self, ticker, start_date=None):
        return [{"date": "2020-01-02", "adjClose": 1.0, "close": 1.0, "volume": 100.0}]


def test_ingest_historical_builds_store_at_backtest_path_and_honors_limit(tmp_path, monkeypatch) -> None:
    """--limit N restricts to the first N tickers AND the ingest writes to the configured backtest path."""
    import fxhnt.cli as cli
    from fxhnt.adapters.warehouse.duckdb_feature_store import DuckDbFeatureStore

    bt_path = tmp_path / "backtest" / "warehouse.duckdb"
    monkeypatch.setenv("FXHNT_BACKTEST_WAREHOUSE_PATH", str(bt_path))
    cli.get_settings.cache_clear()  # the settings are lru_cached — pick up the env override

    # Patch the concrete adapters the command imports (function-local imports -> patch at source module).
    monkeypatch.setattr("fxhnt.adapters.data.tiingo_daily.TiingoDailyClient", lambda *a, **k: _FakeBars())
    monkeypatch.setattr("fxhnt.adapters.data.tiingo_universe.TiingoUniverseSource", lambda *a, **k: _FakeUniverse())

    result = CliRunner().invoke(cli.app, ["ingest-historical", "--limit", "2"])
    cli.get_settings.cache_clear()

    assert result.exit_code == 0, result.output
    assert bt_path.exists(), "ingest must create the warehouse at the configured backtest path"
    assert "2 ingested" in result.output  # only the first 2 of 3 tickers (the --limit)

    # The two limited tickers are in the dedicated warehouse; the third (CCC) is not.
    store = DuckDbFeatureStore(str(bt_path))
    try:
        symbols = {row[0] for row in store.catalog()}
    finally:
        store.close()
    assert symbols == {"AAA", "BBB"}


def test_ingest_historical_full_set_when_no_limit(tmp_path, monkeypatch) -> None:
    """No --limit (0) ingests the FULL survivorship-free set into the backtest warehouse."""
    import fxhnt.cli as cli
    from fxhnt.adapters.warehouse.duckdb_feature_store import DuckDbFeatureStore

    bt_path = tmp_path / "warehouse.duckdb"
    monkeypatch.setenv("FXHNT_BACKTEST_WAREHOUSE_PATH", str(bt_path))
    cli.get_settings.cache_clear()
    monkeypatch.setattr("fxhnt.adapters.data.tiingo_daily.TiingoDailyClient", lambda *a, **k: _FakeBars())
    monkeypatch.setattr("fxhnt.adapters.data.tiingo_universe.TiingoUniverseSource", lambda *a, **k: _FakeUniverse())

    result = CliRunner().invoke(cli.app, ["ingest-historical"])
    cli.get_settings.cache_clear()

    assert result.exit_code == 0, result.output
    store = DuckDbFeatureStore(str(bt_path))
    try:
        symbols = {row[0] for row in store.catalog()}
    finally:
        store.close()
    assert symbols == {"AAA", "BBB", "CCC"}
