"""Earnings calendar guard (audit Phase 7: earnings-event restrictions).

Holding a swing/options position through an earnings report is a gap risk the
risk rules can't control. When enabled, signals for symbols reporting within
EARNINGS_BLACKOUT_DAYS are rejected.

Provider: Finnhub (free API key from finnhub.io → FINNHUB_API_KEY in .env).
Without a key the guard is disabled and clearly reported as such — it never
silently pretends to check (audit rule: mark NOT TESTED rather than passed).
"""
import logging
import os
from datetime import date, timedelta

import httpx

logger = logging.getLogger(__name__)

TIMEOUT = 6.0


def earnings_guard_enabled() -> bool:
    return bool(os.getenv("FINNHUB_API_KEY"))


def blackout_days() -> int:
    try:
        return max(0, int(os.getenv("EARNINGS_BLACKOUT_DAYS", "5")))
    except ValueError:
        return 5


def days_to_next_earnings(symbol: str) -> int | None:
    """Days until the next earnings report, or None if unknown/disabled."""
    key = os.getenv("FINNHUB_API_KEY", "")
    if not key:
        return None
    try:
        today = date.today()
        r = httpx.get(
            "https://finnhub.io/api/v1/calendar/earnings",
            params={"symbol": symbol, "from": today.isoformat(),
                    "to": (today + timedelta(days=21)).isoformat(), "token": key},
            timeout=TIMEOUT,
        )
        r.raise_for_status()
        events = (r.json() or {}).get("earningsCalendar") or []
        dates = []
        for e in events:
            try:
                dates.append(date.fromisoformat(str(e.get("date"))[:10]))
            except ValueError:
                continue
        future = [d for d in dates if d >= today]
        if not future:
            return None
        return (min(future) - today).days
    except Exception as exc:  # noqa: BLE001 — guard failure must not break scans
        logger.warning("Earnings lookup failed for %s: %s", symbol, exc)
        return None
