"""
IPython display helpers — KPI cards, formatted summary blocks, alerts.

Functions are notebook-safe: they fall back to plain ``print`` when running
outside Jupyter / when IPython is not available.
"""

from __future__ import annotations

from typing import Any

try:  # pragma: no cover  – IPython is a soft dep
    from IPython.display import HTML, display

    _IPY = True
except Exception:  # pragma: no cover
    _IPY = False


def _money(value: Any, default: str = "—") -> str:
    try:
        v = float(value)
    except (TypeError, ValueError):
        return default
    if abs(v) >= 1_000_000_000:
        return f"${v/1_000_000_000:,.1f}B"
    if abs(v) >= 1_000_000:
        return f"${v/1_000_000:,.1f}M"
    if abs(v) >= 1_000:
        return f"${v/1_000:,.1f}K"
    return f"${v:,.0f}"


def _pct(value: Any, default: str = "—") -> str:
    try:
        v = float(value)
    except (TypeError, ValueError):
        return default
    return f"{v:,.0f}%"


def _months(value: Any, default: str = "N/A") -> str:
    if value is None:
        return default
    try:
        v = float(value)
    except (TypeError, ValueError):
        return default
    if v < 6:
        return f"<6 months ({v:.1f})"
    return f"{v:.1f} months"


def kpi_cards(summary: dict, *, title: str | None = None) -> Any:
    """
    Render a row of KPI cards (NPV, ROI, Payback, Benefits PV).

    In notebooks, returns/displays inline HTML. Outside IPython, prints a
    plain text version.
    """
    npv = _money(summary.get("npv"))
    roi = _pct(summary.get("roi") or summary.get("roi_pct"))
    payback = _months(summary.get("payback_months"))
    benefits_pv = _money(summary.get("total_benefits_pv"))
    costs_pv = _money(summary.get("total_costs_pv"))

    if not _IPY:  # pragma: no cover
        print(title or "TEI Summary")
        print(f"  NPV: {npv}    ROI: {roi}    Payback: {payback}")
        print(f"  Benefits PV: {benefits_pv}    Costs PV: {costs_pv}")
        return None

    title_html = (
        f'<div style="font-size:1.1em;font-weight:600;margin-bottom:6px;color:#444;">'
        f"{title}</div>"
        if title
        else ""
    )
    card_style = (
        "flex:1;min-width:140px;padding:14px 18px;margin:4px;border-radius:8px;"
        "background:#f7f9fc;border:1px solid #e3e8ee;"
    )
    label_style = "font-size:0.78em;color:#6b7480;text-transform:uppercase;letter-spacing:0.04em;"
    value_style = "font-size:1.6em;font-weight:600;color:#1a2540;margin-top:4px;"

    cards = [
        ("NPV", npv),
        ("ROI", roi),
        ("Payback", payback),
        ("Benefits PV", benefits_pv),
        ("Costs PV", costs_pv),
    ]
    cards_html = "".join(
        f'<div style="{card_style}">'
        f'<div style="{label_style}">{label}</div>'
        f'<div style="{value_style}">{value}</div>'
        f"</div>"
        for label, value in cards
    )
    html = (
        f'<div>{title_html}'
        f'<div style="display:flex;flex-wrap:wrap;align-items:stretch;">{cards_html}</div>'
        f"</div>"
    )
    return display(HTML(html))


def summary_panel(summary: dict, *, title: str = "TEI Financial Summary") -> None:
    """Plain-text bordered summary block (mirrors the PDF Cash Flow Analysis)."""
    width = 60
    print("═" * width)
    print(f"  {title}")
    print("═" * width)
    print(f"  Benefits PV     : {_money(summary.get('total_benefits_pv')):>20}")
    print(f"  Costs PV        : {_money(summary.get('total_costs_pv')):>20}")
    print("─" * width)
    print(f"  NPV             : {_money(summary.get('npv')):>20}")
    roi_val = summary.get("roi") or summary.get("roi_pct")
    print(f"  ROI             : {_pct(roi_val):>20}")
    print(f"  Payback         : {_months(summary.get('payback_months')):>20}")
    print("═" * width)


def alert(text: str, kind: str = "info") -> Any:
    """Coloured alert box for notebooks ('info', 'success', 'warning', 'error')."""
    colors = {
        "info": ("#0277bd", "#e1f5fe"),
        "success": ("#2e7d32", "#e8f5e9"),
        "warning": ("#ef6c00", "#fff3e0"),
        "error": ("#c62828", "#ffebee"),
    }
    fg, bg = colors.get(kind, colors["info"])
    if not _IPY:  # pragma: no cover
        print(f"[{kind.upper()}] {text}")
        return None
    html = (
        f'<div style="padding:10px 14px;border-left:4px solid {fg};'
        f'background:{bg};color:#1a1a1a;border-radius:4px;margin:6px 0;">'
        f"{text}</div>"
    )
    return display(HTML(html))
