"""
Bridges provider-adapter output (app/adapters/schemas.py) into the calculation engines'
dependency-free types (app/engines/types.py). In the real system this is one step inside the
ingestion worker, sitting between "write normalized rows to Postgres" and "read them back as a
FinancialSnapshot for the metrics engine" — exposed as a standalone function here so it can be
exercised directly (see scripts/demo_pipeline_smoke_test.py) without a database.
"""
from __future__ import annotations

from datetime import date
from typing import Optional

from app.adapters.schemas import ProviderFinancialPeriod
from app.engines.types import FinancialSnapshot, LineItems, MarketCapBucket

_LINE_ITEMS_FIELDS = {f for f in LineItems.__dataclass_fields__ if f not in ("security_id", "period_end", "period_type", "filing_date", "currency")}


def provider_period_to_line_items(security_id: str, p: ProviderFinancialPeriod, price: Optional[float] = None) -> LineItems:
    kwargs = {k: v for k, v in p.line_items.items() if k in _LINE_ITEMS_FIELDS}
    shares = kwargs.get("diluted_shares") or kwargs.get("shares_outstanding")
    market_cap = price * shares if (price is not None and shares) else None
    return LineItems(
        security_id=security_id, period_end=p.period_end, period_type=p.period_type,
        filing_date=p.filing_date, currency=p.currency, price=price, market_cap=market_cap, **kwargs,
    )


def market_cap_bucket(market_cap_usd: Optional[float]) -> Optional[MarketCapBucket]:
    """Thresholds in USD millions — configurable in a real deployment; illustrative here."""
    if market_cap_usd is None:
        return None
    if market_cap_usd >= 10_000:
        return MarketCapBucket.LARGE
    if market_cap_usd >= 2_000:
        return MarketCapBucket.MID
    if market_cap_usd >= 300:
        return MarketCapBucket.SMALL
    return MarketCapBucket.MICRO


def build_snapshot(
    security_id: str,
    industry_id: str,
    sector_id: str,
    periods_most_recent_first: list[ProviderFinancialPeriod],
    current_price: Optional[float],
    calculation_date: Optional[date] = None,
    forward_eps_estimate: Optional[float] = None,
) -> FinancialSnapshot:
    if not periods_most_recent_first:
        raise ValueError("Need at least one financial period to build a snapshot")

    line_items = [provider_period_to_line_items(security_id, p, price=current_price if i == 0 else None)
                  for i, p in enumerate(periods_most_recent_first)]
    current, history = line_items[0], line_items[1:]

    mc = current.market_cap
    return FinancialSnapshot(
        security_id=security_id, industry_id=industry_id, sector_id=sector_id,
        market_cap_bucket=market_cap_bucket(mc), calculation_date=calculation_date or date.today(),
        current=current, history=history, forward_eps_estimate=forward_eps_estimate,
    )
