"""
EIA Petroleum Weekly Status Report fetcher.
Uses EIA API v2 — free key stored in DB config as 'eia_api_key'.
"""
import logging
from datetime import datetime
from typing import Any, Dict, List, Optional

import requests

logger = logging.getLogger(__name__)

EIA_BASE_URL = "https://api.eia.gov/v2/petroleum/stoc/wstk/data/"

EIA_SERIES: Dict[str, Dict[str, str]] = {
    "WCRSTUS1": {"name": "US Crude Oil Stocks (ex-SPR)", "unit": "Mb"},
    "WCUOK1A":  {"name": "Cushing, OK Crude Stocks",     "unit": "Mb"},
    "WGTSTUS1": {"name": "US Total Gasoline Stocks",      "unit": "Mb"},
    "WDISTUS1": {"name": "US Distillate Fuel Oil Stocks", "unit": "Mb"},
}

SURPRISE_THRESHOLD_MB = 2.0


def _fetch_series(series_id: str, api_key: str, num_weeks: int = 8) -> List[Dict]:
    params = {
        "api_key": api_key,
        "frequency": "weekly",
        "data[]": "value",
        "facets[series][]": series_id,
        "sort[0][column]": "period",
        "sort[0][direction]": "desc",
        "length": num_weeks,
        "offset": 0,
    }
    try:
        resp = requests.get(EIA_BASE_URL, params=params, timeout=20)
        resp.raise_for_status()
        return resp.json().get("response", {}).get("data", [])
    except Exception as e:
        logger.warning(f"[EIA] Failed to fetch {series_id}: {e}")
        return []


def fetch_eia_report(api_key: str) -> Optional[Dict]:
    """Fetch latest EIA petroleum weekly stocks. Returns None if key missing or all fetches fail."""
    if not api_key:
        logger.warning("[EIA] No API key — skipping")
        return None

    results: Dict[str, Any] = {}
    report_dates: List[str] = []

    for sid, meta in EIA_SERIES.items():
        rows = _fetch_series(sid, api_key)
        if not rows:
            continue
        current = rows[0]
        prior = rows[1] if len(rows) > 1 else None
        cur_val = float(current.get("value") or 0)
        pri_val = float(prior.get("value") or 0) if prior else None
        wow = round(cur_val - pri_val, 1) if pri_val is not None else None

        results[sid] = {
            "name": meta["name"],
            "period": (current.get("period") or "")[:10],
            "value_mb": round(cur_val, 1),
            "prior_mb": round(pri_val, 1) if pri_val is not None else None,
            "wow_change_mb": wow,
        }
        if current.get("period"):
            report_dates.append(current["period"][:10])

    if not results:
        logger.warning("[EIA] No data returned")
        return None

    report_date = max(report_dates) if report_dates else datetime.utcnow().strftime("%Y-%m-%d")

    key_points: List[str] = []
    implications: List[str] = []
    surprises: List[str] = []
    signal_energy = "neutral"

    crude = results.get("WCRSTUS1")
    if crude:
        wow_str = f"{crude['wow_change_mb']:+.1f} Mb" if crude["wow_change_mb"] is not None else "N/A"
        kp = f"US crude oil stocks: {crude['value_mb']:.1f} Mb (WoW {wow_str})"
        if crude["wow_change_mb"] is not None and abs(crude["wow_change_mb"]) >= SURPRISE_THRESHOLD_MB:
            direction = "draw" if crude["wow_change_mb"] < 0 else "build"
            kp += f" — significant {direction}"
            surprises.append("crude")
            signal_energy = "bullish" if crude["wow_change_mb"] < 0 else "bearish"
        key_points.append(kp)

    cushing = results.get("WCUOK1A")
    if cushing:
        wow_str = f"{cushing['wow_change_mb']:+.1f} Mb" if cushing["wow_change_mb"] is not None else "N/A"
        key_points.append(f"Cushing, OK: {cushing['value_mb']:.1f} Mb (WoW {wow_str})")

    gasoline = results.get("WGTSTUS1")
    if gasoline:
        wow_str = f"{gasoline['wow_change_mb']:+.1f} Mb" if gasoline["wow_change_mb"] is not None else "N/A"
        kp = f"US gasoline stocks: {gasoline['value_mb']:.1f} Mb (WoW {wow_str})"
        if gasoline["wow_change_mb"] is not None and abs(gasoline["wow_change_mb"]) >= SURPRISE_THRESHOLD_MB:
            surprises.append("gasoline")
        key_points.append(kp)

    distillates = results.get("WDISTUS1")
    if distillates:
        wow_str = f"{distillates['wow_change_mb']:+.1f} Mb" if distillates["wow_change_mb"] is not None else "N/A"
        kp = f"US distillate stocks: {distillates['value_mb']:.1f} Mb (WoW {wow_str})"
        if distillates["wow_change_mb"] is not None and abs(distillates["wow_change_mb"]) >= SURPRISE_THRESHOLD_MB:
            surprises.append("distillates")
        key_points.append(kp)

    crude_wow = (crude or {}).get("wow_change_mb")
    if crude_wow is not None:
        if crude_wow < -SURPRISE_THRESHOLD_MB:
            implications.append(
                f"Crude draw of {abs(crude_wow):.1f} Mb — bullish for WTI/Brent spot"
            )
        elif crude_wow > SURPRISE_THRESHOLD_MB:
            implications.append(
                f"Crude build of {crude_wow:.1f} Mb — bearish for WTI/Brent spot"
            )

    gasoline_wow = (gasoline or {}).get("wow_change_mb")
    if gasoline_wow is not None and abs(gasoline_wow) >= SURPRISE_THRESHOLD_MB:
        demand_str = "strong" if gasoline_wow < 0 else "weak"
        implications.append(
            f"Gasoline {'draw' if gasoline_wow < 0 else 'build'} ({gasoline_wow:+.1f} Mb) — {demand_str} driving demand"
        )

    if not implications:
        implications = ["EIA petroleum stocks in line with seasonal norms — no major surprise"]

    importance = 3 if len(surprises) >= 2 else 2 if len(surprises) == 1 else 1
    crude_val_str = f"{crude['value_mb']:.1f}" if crude else "N/A"
    crude_wow_str = f" (WoW {crude['wow_change_mb']:+.1f} Mb)" if crude and crude["wow_change_mb"] is not None else ""

    ai_summary = (
        f"EIA Petroleum Weekly ({report_date}). "
        f"Crude: {crude_val_str} Mb{crude_wow_str}. "
        f"Signal: {signal_energy.upper()}. "
        + (f"Surprises: {', '.join(surprises)}. " if surprises else "")
        + implications[0]
    )

    return {
        "report_type": "eia",
        "report_date": report_date,
        "title": f"EIA Petroleum Weekly — {report_date}",
        "source": "EIA API v2",
        "importance": importance,
        "category": "energy",
        "raw_data": results,
        "key_points": key_points,
        "trading_implications": " | ".join(implications),
        "signal_energy": signal_energy,
        "signal_metals": "neutral",
        "signal_indices": "neutral",
        "signal_forex": "neutral",
        "ai_summary": ai_summary,
    }
