from fastapi import APIRouter, Query
from typing import Optional, Dict, Any
from datetime import datetime
from services.data_fetcher import get_all_quotes, get_historical, compute_historical_iv, WATCHLIST

_macro_cache: Dict[str, Any] = {}

router = APIRouter(prefix="/api/market", tags=["market"])


@router.get("/quotes")
def quotes_all():
    return get_all_quotes()


@router.get("/quote/{symbol}")
def quote_single(symbol: str):
    from services.data_fetcher import get_quote
    return get_quote(symbol)


@router.get("/history/{symbol}")
def history(
    symbol: str,
    period: str = Query("1y", description="1d,5d,1mo,3mo,6mo,1y,2y,5y"),
    interval: str = Query("1d", description="1m,5m,15m,1h,1d,1wk,1mo"),
):
    return get_historical(symbol, period, interval)


@router.get("/iv/{symbol}")
def implied_vol(symbol: str, window: int = 30):
    iv = compute_historical_iv(symbol, window)
    return {"symbol": symbol, "iv": iv, "window": window}


@router.get("/watchlist")
def watchlist():
    return WATCHLIST


@router.get("/custom-tickers")
def list_custom_tickers():
    from services.database import get_market_custom_tickers
    return get_market_custom_tickers()


_QUOTE_TYPE_TO_ASSET_CLASS = {
    "CURRENCY": "forex",
    "FUTURE": "energy",
    "INDEX": "indices",
    "ETF": "etfs",
    "EQUITY": "equities",
    "MUTUALFUND": "etfs",
}


@router.post("/custom-tickers/{ticker}")
def add_custom_ticker(ticker: str):
    from services.data_fetcher import get_quote
    from services.database import add_market_custom_ticker
    import yfinance as yf
    ticker = ticker.strip().upper()
    q = get_quote(ticker)
    if not q or not q.get("price"):
        from fastapi import HTTPException
        raise HTTPException(400, f"Ticker '{ticker}' not found on yfinance")
    name = ticker
    asset_class = "custom"
    try:
        info = yf.Ticker(ticker).fast_info
        name = getattr(info, "long_name", None) or getattr(info, "short_name", None) or ticker
        quote_type = getattr(info, "quote_type", "") or ""
        asset_class = _QUOTE_TYPE_TO_ASSET_CLASS.get(quote_type.upper(), "custom")
    except Exception:
        pass
    add_market_custom_ticker(ticker, name, asset_class)
    return {"ticker": ticker, "name": name, "asset_class": asset_class, "price": q["price"]}


@router.delete("/custom-tickers/{ticker}")
def remove_custom_ticker(ticker: str):
    from services.database import remove_market_custom_ticker
    remove_market_custom_ticker(ticker.strip().upper())
    return {"removed": ticker.upper()}


@router.get("/validate")
def validate_ticker(symbol: str = Query(..., description="Ticker to validate against yfinance")):
    """Check if a ticker is fetchable. Returns valid=True + live price/name, or valid=False + reason."""
    from services.data_fetcher import get_quote
    import yfinance as yf
    symbol = symbol.strip().upper()
    q = get_quote(symbol)
    if q and q.get("price"):
        # Try to get a display name
        try:
            info = yf.Ticker(symbol).fast_info
            name = getattr(info, "long_name", None) or getattr(info, "short_name", None) or symbol
        except Exception:
            name = symbol
        return {"valid": True, "symbol": symbol, "name": name, "price": q["price"], "change_pct": q.get("change_pct")}
    return {"valid": False, "symbol": symbol, "reason": f"Ticker '{symbol}' not found on yfinance — check the symbol (e.g. GC=F for Gold, ^GSPC for S&P 500)"}


@router.get("/macro-regime")
def macro_regime(force: bool = False):
    """Macro gauge values + 5-scenario scoring. Cached 15 min."""
    from services.data_fetcher import get_macro_gauges, score_macro_scenarios
    now = datetime.utcnow()
    if not force and _macro_cache.get("data") and _macro_cache.get("ts"):
        age = (now - _macro_cache["ts"]).total_seconds()
        if age < 900:
            return {**_macro_cache["data"], "cached": True, "cache_age_sec": int(age)}
    gauges = get_macro_gauges()
    scenarios = score_macro_scenarios(gauges)
    result: Dict[str, Any] = {
        "gauges": gauges,
        "scenarios": scenarios,
        "fetched_at": now.isoformat(),
        "cached": False,
    }
    _macro_cache["data"] = result
    _macro_cache["ts"] = now

    today = now.strftime("%Y-%m-%d")

    if force:
        # Build a compact gauge summary (key → value + change_pct) for the journal
        gauges_summary = {
            k: {"value": v.get("value"), "change_pct": v.get("change_pct"), "label": v.get("label")}
            for k, v in gauges.items()
            if v.get("value") is not None or v.get("change_pct") is not None
        }
        from services.database import log_macro_regime
        log_macro_regime(
            dominant=scenarios.get("dominant", "incertain"),
            scores=scenarios.get("scores", {}),
            reasons=scenarios.get("reasons", {}),
            gauges_summary=gauges_summary,
        )

    # Always persist full snapshot once per calendar day (all gauges + regime)
    from services.database import save_macro_gauge_snapshot, macro_gauge_snapshot_exists_today
    if force or not macro_gauge_snapshot_exists_today():
        save_macro_gauge_snapshot(
            snapshot_date=today,
            gauges=gauges,
            dominant=scenarios.get("dominant", "incertain"),
            regime_scores=scenarios.get("scores", {}),
        )

    return result


@router.get("/macro-gauges/at")
def macro_gauges_at(date: str = Query(..., description="YYYY-MM-DD")):
    """Return the macro gauge snapshot at or before a given date."""
    from services.database import get_macro_gauge_snapshot_at
    snap = get_macro_gauge_snapshot_at(date)
    if not snap:
        return {"snapshot_date": None, "gauges": {}, "dominant": "incertain", "regime_scores": {}}
    return snap


@router.get("/macro-gauges/history")
def macro_gauges_history(days: int = Query(30, ge=1, le=365)):
    """Return gauge snapshots for the last N days (daily, most recent first)."""
    from services.database import get_macro_gauge_history
    return get_macro_gauge_history(days=days)
