"""
FXStreet economic calendar — upcoming events with consensus forecasts.
No API key required. Endpoint: calendar.fxstreet.com/eventdate/
Covers ~300-400 events over 6 weeks for all major currencies.
"""
import logging
from datetime import datetime, timedelta, date
from typing import Any, Dict

import httpx

logger = logging.getLogger(__name__)

_FXS_URL = "https://calendar.fxstreet.com/eventdate/"

_SUPPORTED_CCY = {"USD", "EUR", "GBP", "JPY", "AUD", "CAD", "NZD", "CHF", "CNY"}

_VOLATILITY = {0: "low", 1: "medium", 2: "high"}

_HEADERS = {
    "Accept": "application/json",
    "User-Agent": (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/125.0.0.0 Safari/537.36"
    ),
    "Origin": "https://www.fxstreet.com",
    "Referer": "https://www.fxstreet.com/economic-calendar",
}


def _parse_dt(dt_str: str) -> tuple[str, str]:
    """'2026-07-04T12:30:00Z' → ('2026-07-04', '12:30')"""
    if not dt_str:
        return "", "00:00"
    try:
        dt_str = dt_str.replace("Z", "+00:00")
        dt = datetime.fromisoformat(dt_str)
        return dt.strftime("%Y-%m-%d"), dt.strftime("%H:%M")
    except Exception:
        return dt_str[:10] if len(dt_str) >= 10 else "", "00:00"


def _fmt(v: Any) -> str | None:
    if v is None:
        return None
    try:
        f = float(v)
        if f != f:
            return None
        return str(int(f)) if f == int(f) else str(round(f, 4))
    except (TypeError, ValueError):
        s = str(v).strip()
        return s or None


def fetch_upcoming(weeks_ahead: int = 6) -> Dict[str, Any]:
    """
    Fetch upcoming economic events from FXStreet (no API key needed).
    One request returns all currencies for the full date range.
    """
    from services.database import get_conn
    from services.ff_calendar import _upsert_batch, FF_TO_FRED

    today = date.today()
    date_to = today + timedelta(weeks=weeks_ahead)

    params = {
        "f":        "json",
        "v":        "2",
        "from":     str(today),
        "to":       str(date_to),
        "timezone": "UTC",
        "culture":  "en-GB",
    }

    print(f"[FXS calendar] fetching {today} → {date_to}", flush=True)

    try:
        resp = httpx.get(
            _FXS_URL, params=params, headers=_HEADERS,
            timeout=30, follow_redirects=True,
        )
        print(f"[FXS calendar] HTTP {resp.status_code}", flush=True)

        if resp.status_code == 403:
            return {"error": "FXStreet blocked this server IP (403). Try again later."}
        if resp.status_code == 429:
            return {"error": "FXStreet rate limit hit (429). Wait a few minutes."}

        resp.raise_for_status()
        events = resp.json()

        if not isinstance(events, list):
            return {"error": f"Unexpected FXStreet response: {str(events)[:200]}"}

    except Exception as e:
        return {"error": f"FXStreet request failed: {e}"}

    batch = []
    skipped = 0
    for ev in events:
        event_obj = ev.get("Event") or {}

        ccy = (event_obj.get("CurrencyId") or "").strip()
        if ccy not in _SUPPORTED_CCY:
            skipped += 1
            continue

        event_name = (event_obj.get("Name") or "").strip()
        if not event_name:
            continue

        dt_str = (ev.get("DateUtc") or "").strip()
        ev_date, ev_time = _parse_dt(dt_str)
        if not ev_date:
            continue

        volatility = ev.get("Volatility")
        impact = _VOLATILITY.get(volatility, "low") if volatility is not None else "low"

        actual   = _fmt(ev.get("Actual"))
        forecast = _fmt(ev.get("Consensus"))
        # Use Revised previous if available, otherwise Previous
        previous = _fmt(ev.get("Revised")) or _fmt(ev.get("Previous"))

        series_id = FF_TO_FRED.get(event_name)

        batch.append((
            ev_date, ev_time, ccy, impact, event_name,
            actual, forecast, previous,
            series_id, None, "fxstreet",
        ))

    conn = get_conn()
    if batch:
        _upsert_batch(conn, batch)
        conn.commit()
    conn.close()

    print(f"[FXS calendar] {len(batch)} upserted, {skipped} skipped (non-major CCY)", flush=True)
    return {
        "total_upserted": len(batch),
        "skipped":        skipped,
        "date_from":      str(today),
        "date_to":        str(date_to),
    }
