"""display_names.py — the SINGLE internal-id -> human-readable name map used by EVERY cockpit view (the
plain-language global constraint: no raw registry id — `multistrat`/`bybit_4edge` — ever reaches an
end user). Absorbs the interim `_SIM_BOOK_LABELS` local map that lived in `app.py` (Task 1) for the
sim/Backtest book pills — those two overrides now live here as the SSOT, and `app.py` reads through this
module instead of its own copy.

Also carries the asset-symbol -> plain "what it is" description used by the holdings table (D2.2/2.3): a
ticker like SPY is fine to show (it is not an internal id), but it is always paired with a plain description
so a non-trader reader understands what they're looking at."""
from __future__ import annotations

from fxhnt.registry import STRATEGY_REGISTRY

# Plain "what it is" description per asset symbol, for the holdings table. The symbol itself is still shown
# (it is not an internal id) — this is the human-readable companion, never a bare ticker alone.
ASSET_DESCRIPTIONS: dict[str, str] = {
    # US listings (the modelled book / us-venue execution)
    "SPY": "US stocks",
    "IEF": "US Treasuries",
    "GLD": "Gold",
    "PDBC": "Commodities",
    "DBMF": "Managed futures",
    # UCITS listings actually HELD in the EU DU account (the multi-strat ETF leg trades these via the UCITS
    # remap — the US ETFs are KID/PRIIPs-blocked). Same plain "what it is" so a holding never reads "other".
    "CSPX": "US stocks",       # iShares Core S&P 500 UCITS  (SPY)
    "CBU0": "US Treasuries",   # iShares $ Treasury 7-10yr UCITS Acc  (IEF, current line)
    "IDTM": "US Treasuries",   # iShares $ Treasury 7-10yr UCITS Dist (IEF, older line still held)
    "IGLN": "Gold",            # iShares Physical Gold ETC  (GLD)
    "ICOM": "Commodities",     # iShares Diversified Commodity Swap UCITS  (PDBC)
}


def display_name(strategy_id: str, fallback: str | None = None) -> str:
    """The ONE human-name resolver for any internal strategy/book id — every cockpit surface calls this so a
    strategy has exactly ONE name everywhere. Reads `STRATEGY_REGISTRY[id]["display_name"]` (the single SSOT;
    no separate override map — the registry display_name IS the cockpit-facing label). The code registry
    always wins for a real strategy; `fallback` (typically the DB `strategy_registry` row's own
    `display_name`) is used ONLY for a sid with no code-registry entry — e.g. a DB-only synthetic probe
    seeded by a test fixture, pruned from every real registry in prod. Absent both, the raw id is the last
    resort so a stray/retired id renders as itself rather than 500-ing a page."""
    entry = STRATEGY_REGISTRY.get(strategy_id)
    if entry is not None:
        return str(entry["display_name"])
    if fallback is not None:
        return fallback
    return strategy_id


def asset_description(symbol: str) -> str:
    """Plain 'what it is' description for an asset symbol (e.g. SPY -> 'US stocks'). An UNMAPPED symbol (a
    future option contract, say) falls back to a plain generic 'other' rather than echoing a raw/odd
    ticker string — the symbol itself is still shown in its own column, so nothing is lost. Never blank,
    never raises."""
    return ASSET_DESCRIPTIONS.get(symbol, "other")
