"""End-to-end vertical slice with a FAKE data provider (no network) + temp SQLite + temp DuckDB.
Proves data → backtest → gauntlet → persistence wires together and the domain stays infra-agnostic."""
from __future__ import annotations

import numpy as np

from fxhnt.adapters.persistence import DuckDbAnalyticalStore, SqlOperationalRepository
from fxhnt.application import ResearchService
from fxhnt.config import GauntletSettings, Settings
from fxhnt.domain.models import AssetClass, Market, PriceSeries, StrategySpec


class FakeDataProvider:
    name = "fake"

    def __init__(self, prices: PriceSeries) -> None:
        self._prices = prices

    def fetch(self, market: Market, start: str | None = None, end: str | None = None) -> PriceSeries:
        return self._prices


def _trending_prices(market: Market, n: int = 2000, seed: int = 1) -> PriceSeries:
    rng = np.random.default_rng(seed)
    rets = rng.normal(0.0004, 0.01, n)  # genuine upward drift -> trend has something real to ride
    close = 100.0 * np.cumprod(1.0 + rets)
    dates = tuple(f"20{10 + i // 365:02d}-{1 + (i // 30) % 12:02d}-{1 + i % 28:02d}" for i in range(n))
    return PriceSeries(market=market, dates=dates, close=close)


def test_vertical_slice(tmp_path) -> None:
    market = Market(symbol="TEST", asset_class=AssetClass.ETF)
    settings = Settings(
        operational_dsn=f"sqlite:///{tmp_path / 'op.db'}",
        analytical_path=str(tmp_path / "an.duckdb"),
        gauntlet=GauntletSettings(),
    )
    svc = ResearchService(
        data=FakeDataProvider(_trending_prices(market)),
        operational=SqlOperationalRepository(settings.operational_dsn),
        analytical=DuckDbAnalyticalStore(settings.analytical_path),
        settings=settings,
    )

    run = svc.evaluate_candidate(market, StrategySpec(kind="trend", params={"window": 100.0}), n_trials=1)

    # the pipeline produced a coherent run
    assert run.stats.n_obs > 1000
    assert run.verdict.n_trials == 1
    # it persisted to the operational store and round-trips
    loaded = svc._op.get_run(run.run_id)  # noqa: SLF001
    assert loaded is not None and loaded.run_id == run.run_id
    assert loaded.verdict.passed == run.verdict.passed
    # the analytical store cached the prices
    assert svc._an.load_prices(market) is not None
