from __future__ import annotations

from datetime import datetime, timezone

import polars as pl
from fastapi.testclient import TestClient

from uforia.api.app import create_app
from uforia.api.settings import ApiSettings
from uforia.storage import DatasetName, DatasetStore


def test_api_exposes_perps_dashboards_and_signals(tmp_path) -> None:
    store = DatasetStore(tmp_path)
    base = datetime(2026, 3, 1, 12, tzinfo=timezone.utc)
    store.write(
        DatasetName.PERPS_SIGNAL_SERIES,
        pl.DataFrame(
            [
                {
                    "ts": base,
                    "date": base.date(),
                    "asset": "BTC",
                    "venue_scope": "all",
                    "source": "perps_family_v1",
                    "basis_bps": 12.5,
                    "funding_rate_1h": 0.0000015,
                    "carry_annualized_pct": 18.2,
                    "carry_zscore_7d": 1.4,
                    "carry_zscore_30d": 1.1,
                    "carry_momentum_1h": 0.3,
                    "carry_momentum_24h": 1.2,
                    "cross_venue_funding_spread": 0.0000003,
                    "long_liq_notional": 500_000.0,
                    "short_liq_notional": 350_000.0,
                    "liq_intensity_zscore": 1.7,
                    "liq_asymmetry": 0.18,
                    "oi_concentration": 0.42,
                    "crowding_score": 1.9,
                    "cascade_risk_score": 2.1,
                    "cascade_regime": "high",
                    "vpin_50": 0.61,
                    "toxic_flow_zscore_4h": 1.2,
                    "toxic_flow_zscore_24h": 0.8,
                    "ofi_persistence": 0.35,
                    "large_trade_ratio": 0.16,
                    "toxicity_regime": "elevated",
                    "oi_change_1h": 3.1,
                    "oi_change_4h": 7.2,
                    "oi_change_24h": 11.5,
                    "price_change_1h": 24.0,
                    "oi_price_divergence": 3.1,
                    "oi_acceleration": 0.8,
                    "leverage_regime": "building",
                    "lead_lag_score": 0.0003,
                    "venue_dislocation_bps": 1.4,
                    "convergence_half_life_secs": 145.0,
                    "price_discovery_leader": "binance",
                    "depth_recovery_speed": 0.8,
                    "spread_bps": 2.3,
                    "spread_zscore_4h": 0.9,
                    "spread_zscore_24h": 1.2,
                    "depth_imbalance_momentum": 0.05,
                    "spread_regime": "normal",
                    "rv_5s": 0.61,
                    "rv_1m": 0.54,
                    "rv_5m": 0.48,
                    "vol_signature_ratio": 1.27,
                    "vol_clustering": 0.36,
                    "rv_regime": "elevated",
                    "cum_delta_acceleration": 15.0,
                    "delta_divergence": 4.0,
                    "absorption_ratio": 750.0,
                    "delta_regime": "aggressive_buying",
                    "quality_flag": "ok",
                }
            ]
        ),
    )
    store.write(
        DatasetName.PERPS_COMPOSITE_SERIES,
        pl.DataFrame(
            [
                {
                    "ts": base,
                    "date": base.date(),
                    "asset": "BTC",
                    "venue_scope": "all",
                    "source": "perps_composite_v1",
                    "carry_score": 1.25,
                    "cascade_risk_score": 2.1,
                    "toxicity_score": 1.05,
                    "positioning_score": 0.88,
                    "fragility_score": 0.66,
                    "quality_flag": "ok",
                }
            ]
        ),
    )

    app = create_app(settings=ApiSettings(data_root=tmp_path), store=store)
    client = TestClient(app)

    dashboards = client.get("/api/v1/perps/dashboards")
    dashboard_series = client.get(
        "/api/v1/perps/funding_basis_carry/series",
        params={"asset": "BTC", "venue_scope": "all"},
    )
    signals = client.get("/api/v1/perps/signals")
    signal_latest = client.get(
        "/api/v1/perps/signals/carry_score/latest",
        params={"asset": "BTC", "venue_scope": "all"},
    )

    assert dashboards.status_code == 200
    assert {
        "funding_basis_carry",
        "liquidation_cascade",
        "order_flow_toxicity",
        "oi_price_divergence",
        "cross_venue_price_discovery",
        "depth_resilience",
        "vol_microstructure",
        "cum_delta_momentum",
    } <= {item["id"] for item in dashboards.json()["data"]}
    assert dashboard_series.status_code == 200
    assert len(dashboard_series.json()["data"]["points"]) == 1
    assert signals.status_code == 200
    assert {
        "carry_score",
        "cascade_risk_score",
        "toxicity_score",
        "positioning_score",
        "fragility_score",
    } <= {item["id"] for item in signals.json()["data"]}
    assert signal_latest.status_code == 200
    assert signal_latest.json()["data"]["latest_values"]["carry_score"] == 1.25


def test_perps_dashboard_quality_uses_dashboard_specific_coverage(tmp_path) -> None:
    store = DatasetStore(tmp_path)
    base = datetime(2026, 3, 1, 12, tzinfo=timezone.utc)
    row = {
        "ts": base,
        "date": base.date(),
        "asset": "BTC",
        "venue_scope": "all",
        "source": "perps_family_v1",
        "basis_bps": 12.5,
        "funding_rate_1h": 0.0000015,
        "carry_annualized_pct": 18.2,
        "carry_zscore_7d": 1.4,
        "carry_zscore_30d": 1.1,
        "carry_momentum_1h": 0.3,
        "carry_momentum_24h": 1.2,
        "cross_venue_funding_spread": None,
        "long_liq_notional": 500_000.0,
        "short_liq_notional": 350_000.0,
        "liq_intensity_zscore": 1.7,
        "liq_asymmetry": 0.18,
        "oi_concentration": 0.42,
        "crowding_score": 1.9,
        "cascade_risk_score": 2.1,
        "cascade_regime": "high",
        "vpin_50": 0.61,
        "toxic_flow_zscore_4h": 1.2,
        "toxic_flow_zscore_24h": None,
        "ofi_persistence": 0.35,
        "large_trade_ratio": 0.16,
        "toxicity_regime": "elevated",
        "oi_change_1h": 3.1,
        "oi_change_4h": 7.2,
        "oi_change_24h": 11.5,
        "price_change_1h": 24.0,
        "oi_price_divergence": 3.1,
        "oi_acceleration": 0.8,
        "leverage_regime": "building",
        "lead_lag_score": None,
        "venue_dislocation_bps": 1.4,
        "convergence_half_life_secs": 145.0,
        "price_discovery_leader": "binance",
        "depth_recovery_speed": 0.8,
        "spread_bps": 2.3,
        "spread_zscore_4h": 0.9,
        "spread_zscore_24h": 1.2,
        "depth_imbalance_momentum": 0.05,
        "spread_regime": "normal",
        "rv_5s": 0.61,
        "rv_1m": 0.54,
        "rv_5m": 0.48,
        "vol_signature_ratio": 1.27,
        "vol_clustering": 0.36,
        "rv_regime": "elevated",
        "cum_delta_acceleration": 15.0,
        "delta_divergence": 4.0,
        "absorption_ratio": 750.0,
        "delta_regime": "aggressive_buying",
        "quality_flag": "partial_context",
    }
    store.write(DatasetName.PERPS_SIGNAL_SERIES, pl.DataFrame([row]))

    app = create_app(settings=ApiSettings(data_root=tmp_path), store=store)
    client = TestClient(app)
    latest = client.get(
        "/api/v1/perps/order_flow_toxicity/latest",
        params={"asset": "BTC", "venue_scope": "all"},
    )

    assert latest.status_code == 200
    assert latest.json()["data"]["latest_quality"] == "ok"
