"""
Macro Context (StockLab overhaul, Part 15 — new, informational-only layer).

**Status: SCAFFOLD.** This module defines the shape a macro-context payload should have —
policy rates, inflation, GDP growth, unemployment, commodity prices, FX, credit spreads — each as
an explicitly-sourced `MacroDataPoint` (value + `as_of` + `source`, so a consumer can tell a
figure is 3 months stale). It does **not** ingest anything: there is no macro-data provider
adapter in this codebase (`app/adapters/` has FMP/EODHD/Demo company-fundamentals adapters only),
and this build's network egress cannot reach a macro data source to build or test one against real
data (see docs/TROUBLESHOOTING.md's provider-adapter network note, which applies equally here).
Building `MacroDataPoint` instances is therefore left to a future provider adapter this pass does
not implement — populating this module with plausible-looking numbers when there is no real feed
behind them would be exactly the kind of fabricated data this audit is required to avoid.

**Structural guarantee, verified by this audit, not just asserted:** nothing in
`app/engines/scoring/`, `app/engines/valuation/`, or `app/engines/recommendation/` imports from
`app.engines.macro` — confirmed by `grep -rn "engines.macro" backend/app/engines/{scoring,
valuation,recommendation}` returning zero matches. Macro Context is designed to stay a pure
display/context layer: if a future pass wants it to influence the Investment Score, that requires
the same "verify empirically before wiring" step spec §57 and this audit apply to every other
threshold, and should NOT happen by a scoring engine casually importing this module.
"""
from __future__ import annotations

from dataclasses import dataclass
from datetime import date
from typing import Optional


@dataclass(frozen=True)
class MacroDataPoint:
    value: Optional[float]
    as_of: Optional[date]
    source: Optional[str]  # provider name, e.g. "FRED", "TRADING_ECONOMICS" — never fabricated


@dataclass(frozen=True)
class MacroContext:
    """One country/region's macro snapshot. All fields optional and independently sourced —
    a consumer must be able to render partial macro context (e.g. rates known, inflation
    unknown) rather than an all-or-nothing block, consistent with every other engine's
    INSUFFICIENT-DATA-per-field discipline."""

    region: str  # ISO country code or region label, e.g. "US", "EU"
    policy_rate: Optional[MacroDataPoint] = None
    ten_year_yield: Optional[MacroDataPoint] = None
    cpi_yoy: Optional[MacroDataPoint] = None
    gdp_growth_yoy: Optional[MacroDataPoint] = None
    unemployment_rate: Optional[MacroDataPoint] = None
    credit_spread_ig: Optional[MacroDataPoint] = None  # investment-grade credit spread, bps
    fx_rate_to_usd: Optional[MacroDataPoint] = None
    commodity_index: Optional[MacroDataPoint] = None

    @property
    def populated_field_count(self) -> int:
        fields = [
            self.policy_rate, self.ten_year_yield, self.cpi_yoy, self.gdp_growth_yoy,
            self.unemployment_rate, self.credit_spread_ig, self.fx_rate_to_usd, self.commodity_index,
        ]
        return sum(1 for f in fields if f is not None and f.value is not None)


MACRO_CONTEXT_DISCLAIMER = (
    "Macro context is informational only and does not influence Score, Confidence, Data Quality, "
    "or the Buy/Sell recommendation for any security. No macro data provider is wired into this "
    "build. Note: an earlier revision of this string pointed at an audit document for this "
    "module that was never written. This module has no dedicated audit doc; "
    "docs/FINAL_REPORT.md is where its status is recorded."
)
