"""
options_routes.py — Options Quant REST Endpoints
=================================================
Quantum Terminal | Phase 4F — Options Quant Engine

Wire into data_server.py:
    from options_routes import create_options_router
    app.include_router(create_options_router())

Endpoints:
    GET /api/options/symbols          — supported canonical assets + Yahoo mapping
    GET /api/options/{ticker}/snapshot — full metrics (GEX + levels + IV divergence)
    GET /api/options/{ticker}/chain   — raw calls/puts chain data
    GET /api/options/{ticker}/expiries — available expiry dates from Yahoo
"""

import logging
from pathlib import Path
from fastapi import APIRouter, HTTPException, Query
from typing import Optional

log = logging.getLogger("mk.options_routes")

PROJECT_ROOT = Path(__file__).resolve().parent


def create_options_router() -> APIRouter:
    router = APIRouter(tags=["options"])

    from options_data_manager import get_options_dm, OPTIONS_SYMBOL_MAP
    from options_engine import compute_all, compute_all_multi

    @router.get("/api/options/symbols")
    async def get_options_symbols():
        """
        Return list of assets with options support and their Yahoo mappings.
        """
        return {
            "supported": [
                {"canonical": k, "cboe_ticker": v}
                for k, v in OPTIONS_SYMBOL_MAP.items()
            ]
        }

    @router.get("/api/options/{ticker}/snapshot")
    async def get_options_snapshot(
        ticker: str,
        expiry: Optional[str] = Query(None, description="ISO date e.g. 2025-03-21"),
    ):
        """
        Full options analytics snapshot for one asset.
        Includes GEX, flip level, max pain, walls, P/C ratio, IV divergence.
        Response is cached 15 minutes — stale data served outside market hours.
        """
        canonical = ticker.upper()
        if canonical not in OPTIONS_SYMBOL_MAP:
            raise HTTPException(
                404,
                f"{canonical} not supported. Supported: {list(OPTIONS_SYMBOL_MAP.keys())}"
            )

        odm = get_options_dm()
        snap = odm.get_snapshot(canonical, expiry=expiry)

        if snap is None:
            raise HTTPException(503, f"Could not fetch options data for {canonical}. "
                                     f"Check yfinance install and network.")

        try:
            metrics = compute_all(snap)
        except Exception as e:
            log.error(f"Options engine error for {canonical}: {e}")
            raise HTTPException(500, f"Options calculation failed: {e}")

        return metrics

    @router.get("/api/options/{ticker}/chain")
    async def get_options_chain(
        ticker: str,
        expiry: Optional[str] = Query(None),
    ):
        """
        Raw options chain (calls + puts) for one asset and expiry.
        Useful for frontend to render custom strike tables.
        """
        canonical = ticker.upper()
        if canonical not in OPTIONS_SYMBOL_MAP:
            raise HTTPException(404, f"{canonical} not supported")

        odm = get_options_dm()
        snap = odm.get_snapshot(canonical, expiry=expiry)

        if snap is None:
            raise HTTPException(503, f"Could not fetch chain for {canonical}")

        return {
            "canonical":   snap["canonical"],
            "cboe_ticker": snap.get("cboe_ticker"),
            "expiry":      snap.get("expiry"),
            "spot":        snap.get("spot"),
            "calls":       snap.get("calls", []),
            "puts":        snap.get("puts",  []),
            "cached_at":   snap.get("cached_at"),
            "is_stale":    snap.get("is_stale", False),
        }

    @router.get("/api/options/{ticker}/expiries")
    async def get_options_expiries(ticker: str):
        """Available expiry dates. Returns list of ISO date strings."""
        canonical = ticker.upper()
        if canonical not in OPTIONS_SYMBOL_MAP:
            raise HTTPException(404, f"{canonical} not supported")
        odm = get_options_dm()
        return {"canonical": canonical, "expiries": odm.get_available_expiries(canonical)}

    @router.get("/api/options/{ticker}/full")
    async def get_options_full(
        ticker: str,
        n: int = Query(8, description="Number of expiries for GEX stack (1-12)"),
    ):
        """
        Full multi-expiry options analytics.
        Includes GEX stack (GEX1–GEXn), 0DTE GEX, HVL, expected move.
        This is the primary endpoint for the enhanced OPTIONS QUANT UI.
        """
        canonical = ticker.upper()
        if canonical not in OPTIONS_SYMBOL_MAP:
            raise HTTPException(404, f"{canonical} not supported")

        odm = get_options_dm()
        n = max(1, min(n, 12))
        snap = odm.get_full_snapshot(canonical, n_expiries=n)
        if snap is None:
            raise HTTPException(503, f"Could not fetch options data for {canonical}")

        try:
            return compute_all_multi(snap)
        except Exception as e:
            log.error(f"Options multi-expiry calc error {canonical}: {e}")
            raise HTTPException(500, f"Calculation failed: {e}")

    return router