"""
Canonical, provider-agnostic shapes that every ProviderAdapter must return (docs/DATA_SOURCES.md
§7). The calculation engines never see a provider-specific field name — normalization from these
shapes into `app.engines.types.LineItems` / DB rows happens once, in
`app/workers/normalize.py`, not scattered across the codebase.
"""
from __future__ import annotations

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


@dataclass(frozen=True)
class ProviderCompanyProfile:
    ticker: str
    exchange_mic: Optional[str]
    legal_name: str
    display_name: str
    country_iso2: Optional[str]
    sector: Optional[str]
    industry: Optional[str]
    currency: str
    isin: Optional[str] = None
    website: Optional[str] = None
    description: Optional[str] = None
    beta: Optional[float] = None


@dataclass(frozen=True)
class ProviderFinancialPeriod:
    """One reporting period's worth of raw line items, provider-normalized field names already
    mapped to our canonical keys (this dataclass's field names == LineItems' field names so the
    mapping in app/engines/types.LineItems(**asdict(provider_period_minus_meta)) is direct)."""

    period_end: date
    period_type: str
    filing_date: Optional[date]
    currency: str
    line_items: dict  # canonical field name -> value, matches LineItems fields (see types.py)


@dataclass(frozen=True)
class ProviderPriceBar:
    date: date
    open: Optional[float]
    high: Optional[float]
    low: Optional[float]
    close: float
    adjusted_close: Optional[float]
    volume: Optional[float]
    currency: str


@dataclass(frozen=True)
class ProviderEstimateRow:
    period_end: date
    metric: str
    consensus_value: Optional[float]
    num_analysts: Optional[int]
    as_of_date: date


@dataclass(frozen=True)
class ProviderDividendRow:
    ex_date: date
    pay_date: Optional[date]
    amount_per_share: float
    currency: str
    is_special: bool = False
