"""
Trading Economics calendar service — upcoming events with consensus forecasts.
NOTE: confirmed (2026-07) that the calendar endpoint is NOT actually free despite the
signup page — their base paid plan is $149/month. Kept wired in case a key is ever
available, but don't recommend this as a free option (same dead end as FMP, whose
free tier also excludes the economic_calendar endpoint — needs their $14.99/mo Starter).
Signup: https://tradingeconomics.com/api/login
Endpoint: GET https://api.tradingeconomics.com/calendar/country/united%20states?c=KEY
"""
import logging
from datetime import datetime, timezone, timedelta, date
from typing import Any, Dict, List, Optional

import httpx

logger = logging.getLogger(__name__)

_TE_BASE = "https://api.tradingeconomics.com"

# TE country names → our currency codes
_TE_COUNTRY_TO_CCY: Dict[str, str] = {
    "united states": "USD",
    "euro area":     "EUR",
    "united kingdom":"GBP",
    "japan":         "JPY",
    "australia":     "AUD",
    "canada":        "CAD",
    "new zealand":   "NZD",
    "switzerland":   "CHF",
    "china":         "CNY",
}

# TE importance (1=low, 2=medium, 3=high) → our impact labels
_TE_IMPORTANCE = {1: "low", 2: "medium", 3: "high"}

_COUNTRIES = list(_TE_COUNTRY_TO_CCY.keys())


def _get_te_key() -> str:
    from services.database import get_config
    return (get_config("te_api_key") or "").strip()


def check_te_key() -> Dict[str, Any]:
    key = _get_te_key()
    return {
        "configured": bool(key),
        "preview": (key[:4] + "…" + key[-4:]) if len(key) > 8 else ("***" if key else ""),
    }


def _parse_te_datetime(dt_str: str) -> tuple[str, str]:
    """Parse TE datetime '2026-07-04T12:30:00' (UTC) → (date, time)."""
    if not dt_str:
        return "", "00:00"
    try:
        # TE returns UTC datetimes
        dt = datetime.fromisoformat(dt_str.replace("Z", "+00:00"))
        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 fetch_upcoming(weeks_ahead: int = 6) -> Dict[str, Any]:
    """
    Fetch upcoming calendar events from Trading Economics API and upsert into ff_calendar.
    Covers today → today + weeks_ahead weeks.
    """
    from services.database import get_conn
    from services.ff_calendar import _upsert_batch, FF_TO_FRED, SUPPORTED_CURRENCIES

    key = _get_te_key()
    if not key:
        return {"error": "Trading Economics API key not configured. Register free at tradingeconomics.com/api/login"}

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

    params = {
        "c":         key,
        "d1":        str(today),
        "d2":        str(date_to),
        "importance": "1,2,3",          # all impact levels
    }

    total_inserted = 0
    conn = get_conn()

    for country in _COUNTRIES:
        ccy = _TE_COUNTRY_TO_CCY[country]
        try:
            url = f"{_TE_BASE}/calendar/country/{country.replace(' ', '%20')}"
            resp = httpx.get(url, params=params, timeout=20, follow_redirects=True)
            print(f"[TE calendar] {country}: HTTP {resp.status_code}", flush=True)

            if resp.status_code == 401:
                conn.close()
                return {"error": "Invalid Trading Economics API key"}
            if resp.status_code == 403:
                conn.close()
                return {"error": "TE API key quota exceeded or invalid plan"}

            resp.raise_for_status()
            events = resp.json()
            if not isinstance(events, list):
                continue

            batch = []
            for ev in events:
                event_name = (ev.get("Event") or ev.get("event") or "").strip()
                if not event_name:
                    continue

                importance = ev.get("Importance") or ev.get("importance") or 1
                impact = _TE_IMPORTANCE.get(int(importance), "low")

                dt_str = ev.get("Date") or ev.get("date") or ""
                ev_date, ev_time = _parse_te_datetime(dt_str)
                if not ev_date:
                    continue

                actual   = _fmt_val(ev.get("Actual")   or ev.get("actual"))
                forecast = _fmt_val(ev.get("Forecast")  or ev.get("forecast"))
                previous = _fmt_val(ev.get("Previous")  or ev.get("previous"))

                series_id = FF_TO_FRED.get(event_name)

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

            if batch:
                _upsert_batch(conn, batch)
                conn.commit()
                total_inserted += len(batch)
                print(f"[TE calendar] {country}: {len(batch)} events upserted", flush=True)

        except Exception as e:
            logger.warning(f"[TE calendar] {country}: {e}")
            print(f"[TE calendar] {country} error: {e}", flush=True)

    conn.close()
    return {
        "total_upserted": total_inserted,
        "date_from":      str(today),
        "date_to":        str(date_to),
        "countries":      len(_COUNTRIES),
    }


def _fmt_val(v: Any) -> str:
    """Convert TE numeric value to string, return empty if None/NaN."""
    if v is None:
        return ""
    try:
        f = float(v)
        if f != f:  # NaN check
            return ""
        # Format cleanly: no trailing .0 for integers
        return str(int(f)) if f == int(f) else str(round(f, 4))
    except (TypeError, ValueError):
        return str(v).strip()
