"""Display-layer formatters reused across MEL templates, exports and emails."""
from __future__ import annotations

from datetime import date, datetime
from decimal import Decimal, InvalidOperation
from typing import Any


# ---------------------------------------------------------------------------
# RAG
# ---------------------------------------------------------------------------

RAG_LABELS = {
    "green": "On track",
    "amber": "At risk",
    "red": "Off track",
    "unknown": "Unknown",
}


def rag_label(status: str | None) -> str:
    if status is None:
        return RAG_LABELS["unknown"]
    return RAG_LABELS.get(str(status).lower(), RAG_LABELS["unknown"])


# ---------------------------------------------------------------------------
# Percent / currency / date / text
# ---------------------------------------------------------------------------


def format_percent(value: Any, *, decimals: int = 1) -> str:
    """Format a 0–100 value as a percent string (``None`` → ``'—'``)."""
    if value is None:
        return "—"
    try:
        v = float(value)
    except (TypeError, ValueError):
        return "—"
    return f"{v:.{decimals}f}%"


def format_currency(value: Any, *, currency: str = "USD", decimals: int = 2) -> str:
    if value is None:
        return "—"
    try:
        v = Decimal(str(value))
    except (InvalidOperation, TypeError, ValueError):
        return "—"
    return f"{currency} {v:,.{decimals}f}"


def format_date(value: date | datetime | None, *, fmt: str = "%d %b %Y") -> str:
    if value is None:
        return "—"
    if isinstance(value, datetime):
        value = value.date()
    return value.strftime(fmt)


def truncate(text: str | None, *, length: int = 80) -> str:
    if not text:
        return ""
    if len(text) <= length:
        return text
    return text[: length - 1].rstrip() + "…"
