"""
Simulator baseline endpoint.
Returns current market values to seed the EUR/USD causal simulator.
Sources (priority): macro_gauge_snapshots → FRED economic_events → yfinance → hardcoded fallbacks.
"""
import json
import logging
from datetime import datetime
from fastapi import APIRouter

router = APIRouter()
logger = logging.getLogger(__name__)

_FALLBACK = {
    "fed_rate":       4.25,
    "ecb_rate":       3.65,
    "us_2y":          4.50,
    "us_10y":         4.30,
    "eu_2y":          2.80,
    "eu_10y":         2.60,
    "eurusd":         1.1450,
    "vix":            18.0,
    "oil":            80.0,
    "real_yield_us":  2.10,
    "pmi_us":         50.0,
    "pmi_eu":         50.0,
}


def _gauge_val(gauges: dict, key: str):
    g = gauges.get(key, {})
    v = g.get("value")
    return float(v) if v is not None else None


def _yf_last(sym: str):
    """Download last closing price for a single yfinance symbol."""
    try:
        import yfinance as yf
        df = yf.download(sym, period="5d", interval="1d", progress=False, auto_adjust=True)
        if df is None or len(df) == 0:
            return None
        if hasattr(df.columns, "levels"):
            df.columns = df.columns.get_level_values(0)
        close = df["Close"].dropna()
        return float(close.iloc[-1]) if len(close) > 0 else None
    except Exception as e:
        logger.debug(f"[simulator/baseline] yf {sym}: {e}")
        return None


@router.get("/api/simulator/baseline")
def simulator_baseline():
    """
    Aggregate current market values for the EUR/USD simulator.
    Returns: fed_rate, ecb_rate, us_2y, eu_2y, eurusd, vix, oil, real_yield_us, sources{}, fetched_at.
    """
    result = dict(_FALLBACK)
    sources: dict = {}

    # ── 1. Macro gauge snapshots (fast, already in DB) ──────────────────────
    try:
        from services.database import get_conn
        conn = get_conn()
        row = conn.execute(
            "SELECT gauges, snapshot_date FROM macro_gauge_snapshots ORDER BY snapshot_date DESC LIMIT 1"
        ).fetchone()
        conn.close()
        if row:
            raw = row["gauges"]
            gauges = raw if isinstance(raw, dict) else json.loads(raw or "{}")
            snap_date = (row["snapshot_date"] or "")[:10]

            v = _gauge_val(gauges, "vix")
            if v:
                result["vix"] = round(v, 1)
                sources["vix"] = f"snapshot {snap_date}"

            v = _gauge_val(gauges, "brent")
            if v:
                result["oil"] = round(v, 1)
                sources["oil"] = f"snapshot {snap_date}"

            # US 10Y from gauge snapshot (yfinance will override if available)
            v = _gauge_val(gauges, "us10y")
            if v:
                result["us_10y"] = round(v, 2)
                sources["us_10y"] = f"snapshot {snap_date}"

    except Exception as e:
        logger.debug(f"[simulator/baseline] gauge query: {e}")

    # ── 2. FRED economic_events (policy rates, real yield) ──────────────────
    try:
        from services.database import get_conn
        conn = get_conn()

        for series_id, field in [
            ("FEDFUNDS", "fed_rate"),
            ("DFF",      "fed_rate"),     # daily effective fed funds (fallback)
            ("ECBDFR",   "ecb_rate"),     # ECB deposit facility rate
            ("DFII10",   "real_yield_us"),# 10-year TIPS yield (real yield)
        ]:
            if field in sources:
                continue
            row = conn.execute(
                "SELECT actual_value FROM economic_events WHERE series_id=? ORDER BY event_date DESC LIMIT 1",
                (series_id,),
            ).fetchone()
            if row and row[0] is not None:
                result[field] = round(float(row[0]), 2)
                sources[field] = f"FRED {series_id}"

        conn.close()
    except Exception as e:
        logger.debug(f"[simulator/baseline] FRED query: {e}")

    # ── 3. yfinance live quotes ─────────────────────────────────────────────
    try:
        # EURUSD spot
        v = _yf_last("EURUSD=X")
        if v:
            result["eurusd"] = round(v, 4)
            sources["eurusd"] = "yfinance EURUSD=X"

        # US Treasury yields (yfinance returns annualised %)
        irx = _yf_last("^IRX")   # 13-week T-bill (0.25Y)
        fvx = _yf_last("^FVX")   # 5-year T-note
        tnx = _yf_last("^TNX")   # 10-year T-note

        if irx and fvx:
            # Linear interpolation for 2Y on [0.25Y, 5Y] segment
            # position of 2Y: (2 - 0.25) / (5 - 0.25) ≈ 0.368
            us2y = irx + 0.368 * (fvx - irx)
            result["us_2y"] = round(us2y, 2)
            sources["us_2y"] = "yfinance ^IRX+^FVX interp"
        elif tnx:
            result["us_2y"] = round(tnx * 0.92, 2)  # rough proxy
            sources["us_2y"] = "yfinance ^TNX proxy"

        # US 10Y (^TNX)
        if tnx:
            result["us_10y"] = round(tnx, 2)
            sources["us_10y"] = "yfinance ^TNX"

        # Real yield: 10Y nominal minus 10Y breakeven inflation via TIPS
        if tnx and "real_yield_us" not in sources:
            # TIPS yield approximation: nominal - 2.3% (rough breakeven)
            result["real_yield_us"] = round(tnx - 2.3, 2)
            sources["real_yield_us"] = "yfinance ^TNX - breakeven approx"

        # EU 2Y — German Schatz (not always available on yfinance)
        eu2y = _yf_last("DE2YT=RR")
        if eu2y:
            result["eu_2y"] = round(eu2y, 2)
            sources["eu_2y"] = "yfinance DE2YT=RR"
        else:
            # Approximation: ECB rate + 15 bps market premium
            result["eu_2y"] = round(result["ecb_rate"] + 0.15, 2)
            sources["eu_2y"] = "ECB rate +15bps approx"

        # EU 10Y — German Bund 10Y
        eu10y = _yf_last("GE10YT=RR")
        if eu10y:
            result["eu_10y"] = round(eu10y, 2)
            sources["eu_10y"] = "yfinance GE10YT=RR"
        else:
            # Approximation: ECB rate + term premium ~200bps
            result["eu_10y"] = round(result["ecb_rate"] + 2.0, 2)
            sources["eu_10y"] = "ECB rate +200bps approx"

        # VIX — override gauge if not already set from DB
        if "vix" not in sources:
            v = _yf_last("^VIX")
            if v:
                result["vix"] = round(v, 1)
                sources["vix"] = "yfinance ^VIX"

        # Brent — override gauge if not already set
        if "oil" not in sources:
            v = _yf_last("BZ=F")
            if v:
                result["oil"] = round(v, 1)
                sources["oil"] = "yfinance BZ=F"

    except Exception as e:
        logger.debug(f"[simulator/baseline] yfinance block: {e}")

    # ── Cleanup & return ────────────────────────────────────────────────────
    result["sources"]    = sources
    result["fetched_at"] = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
    return result
