"""Telegram message formatter for heartbeat monitoring."""

from __future__ import annotations

import html
import re
import socket
import time

from heartbeat.checks.resources import RESOURCE_WINDOW_MINUTES
from heartbeat.config import get_heartbeat_symbols


def format_message(results: dict[str, bool | str], healthy: bool) -> str:
    """Format health check results as a sectioned Telegram message."""
    host = socket.gethostname()
    now = time.strftime("%H:%M:%S UTC", time.gmtime())

    def _icon(key: str) -> str:
        v = results.get(key)
        if v is True:
            return "\u2705"
        if v is False:
            return "\u274c"
        return "\u2139\ufe0f"

    # Per-check remediation hints for UNHEALTHY state
    _remediation = {
        "clickhouse": "Check: systemctl status clickhouse-server",
        "sidecar": "Check: journalctl --user -u opendeviationbar-sidecar -n 20",
        "kintsugi": "Check: journalctl --user -u opendeviationbar-kintsugi -n 20",
        "kintsugi_telemetry": "Kintsugi may be stuck or crashed — check journal",
        "kintsugi_stuck": "Repair running too long — check REST rate limits or CH writes",
        "kintsugi_failures": "Multiple repairs failing — check Binance Vision data + CH health",
        "stathera_gaps": "Pipeline bar-boundary gaps detected — kintsugi day-recompute will resolve (exchange gaps excluded from alerting)",
        "stathera_overlaps": "Duplicate bars from different sidecar instances awaiting ReplacingMergeTree merge — not data loss",
        "stathera_today_gaps": "TODAY's gaps - sidecar issue, kintsugi cannot fix (#280). Check: journalctl --user -u opendeviationbar-sidecar -n 50",
        "stathera_today_overlaps": "TODAY's overlaps - check for mutation cascade or straddle bars. Check: journalctl --user -u opendeviationbar-sidecar -n 50",
        "disk": "Disk space critical — check du -sh /var/lib/clickhouse/",
        "circuit_breaker": "CH writes blocked — check: curl -s 'http://localhost:8123/?query=SELECT+1'",
        "version_drift": "Version mismatch! Run: mise run deploy:bigblack",
        "seeder_ok": "Seeder timer stale or symbol failed — journalctl --user -u opendeviationbar-seeder -n 30",
        "yesterday_completion": "Aion freshness check failed -- see Per-Symbol Health section",
        "ws_errors_healthy": "429/IP ban from Binance — sidecar violating rate limits. Check journal for details",
        "checksum_ok": "Checksum verification failure — check: cat ~/.cache/opendeviationbar/checksum-telemetry.jsonl | tail -20",
        "ch_writer_dead_letters_ok": "Rust CH writer dead letters — bars lost. Check: journalctl --user -u opendeviationbar-sidecar -n 50 | grep ch_writer",
    }

    health_level = str(results.get("_health_level", "healthy" if healthy else "critical"))

    _headers = {
        "healthy": f"\U0001f49a <b>Heartbeat OK</b> \u2014 {host} @ {now}",
        "degraded": f"\U0001f7e1 <b>Heartbeat DEGRADED</b> \u2014 {host} @ {now}",
        "warning": f"\U0001f7e0 <b>Heartbeat WARNING</b> \u2014 {host} @ {now}",
        "critical": f"\U0001f534 <b>CRITICAL</b> \u2014 {host} @ {now}",
    }
    lines = [_headers.get(health_level, _headers["critical"])]

    if health_level != "healthy":
        failed_checks = [k for k in _remediation if results.get(k) is False]
        if failed_checks:
            lines.append("")
            label = "Likely cause" if health_level == "critical" else "Issues"
            lines.append(f"<b>{label}</b>")
            for k in failed_checks:
                lines.append(f"  \u2192 {k}: {_remediation[k]}")

    # -- Services (with uptime + memory) --
    lines.append("")
    lines.append("<b>Services</b>")
    lines.append(f"  {_icon('clickhouse')} clickhouse")
    for svc in ("sidecar", "kintsugi"):
        uptime = str(results.get(f"{svc}_uptime", ""))
        mem = str(results.get(f"{svc}_mem", ""))
        suffix_parts = []
        if uptime:
            suffix_parts.append(f"{uptime} \u2191")
        if mem:
            suffix_parts.append(f"{mem} MB")
        suffix = f" ({', '.join(suffix_parts)})" if suffix_parts else ""
        lines.append(f"  {_icon(svc)} {svc}{suffix}")

        # Restart diagnostic: hint to check fill_from_rest logs when sidecar recently restarted
        if svc == "sidecar" and uptime:
            m = re.match(r"^(\d+)m$", uptime)
            if m and int(m.group(1)) < 30:
                lines.append(
                    "    \u21b3 recently restarted \u2014 check fill_from_rest drain: "
                    "journalctl --user -u opendeviationbar-sidecar --since '30 min ago' | grep sync_flush"
                )

    # Seeder (timer-driven oneshot — no persistent PID, shown in Services)
    if "seeder_ok" in results:
        status = results.get("seeder_status", "")
        if status == "running":
            running_min = results.get("seeder_running_min", "?")
            cur_sym = results.get("seeder_current_symbol", "")
            months_done = results.get("seeder_months_done", "")
            days_done = results.get("seeder_days_done", "")
            journal_month = results.get("seeder_journal_month", "")
            journal_line = results.get("seeder_journal_line", "")
            progress_parts = []
            if cur_sym:
                progress_parts.append(cur_sym)
                if months_done:
                    progress_parts.append(f"{months_done}mo")
                if days_done:
                    progress_parts.append(f"{days_done}d")
            elif journal_month:
                progress_parts.append(journal_month)
            progress = f" ({', '.join(progress_parts)})" if progress_parts else ""
            lines.append(
                f"  {_icon('seeder_ok')} seeder \u23f3 running {running_min}{progress}"
            )
            if journal_line and not cur_sym:
                lines.append(f"    \u21b3 {journal_line}")
        else:
            age = results.get("seeder_age_min", "?")
            seeded = results.get("seeder_seeded", "?")
            elapsed = results.get("seeder_elapsed", "?")
            sym_detail = results.get("seeder_symbols", "")
            detail = f"{age} ago, {seeded}d seeded, {elapsed}s"
            if sym_detail:
                detail += f" ({sym_detail})"
            lines.append(f"  {_icon('seeder_ok')} seeder {detail}")
        failed = results.get("seeder_failed", "")
        if failed and failed != "0":
            lines.append(
                f"    \u274c {failed} symbol(s) failed\n"
                "      \u2192 journalctl --user -u opendeviationbar-seeder -n 30 | grep -i failed"
            )

    # OOM kill warnings (Issue #185)
    for svc in ("sidecar", "kintsugi"):
        oom_count = results.get(f"{svc}_oom")
        if oom_count:
            lines.append(
                f"  \U0001f4a5 {svc}: {oom_count} OOM kill(s) in 30min!\n"
                f"      \u2192 journalctl --user -u opendeviationbar-{svc} --since '30 min ago' | grep -i oom"
            )

    # Systemd override warnings (Issue #185)
    overrides_str = results.get("systemd_overrides", "")
    if overrides_str:
        lines.append(f"  \u26a0\ufe0f overrides active: {overrides_str}")

    # -- Version Drift (Issue #250) --
    if "version_drift" in results:
        installed = results.get("version_installed", "?")
        detail = results.get("version_drift_detail", "")
        if results["version_drift"] is True:
            if "hotfix" in detail:
                lines.append("")
                lines.append(f"<b>Version</b>: {detail} \U0001f529")
            else:
                lines.append("")
                lines.append(f"<b>Version</b>: v{installed} \u2705")
                if "auto_healed_pth" in results:
                    lines.append(
                        f"  \U0001f527 auto-healed: editable .pth removed"
                        f" (<code>{html.escape(results['auto_healed_pth'])}</code>)"
                    )
        else:
            lines.append("")
            lines.append("<b>Version</b>")
            lines.append(f"  \u274c <b>DRIFT</b>: {html.escape(detail)}")
            lines.append("      \u2192 <code>mise run deploy:bigblack</code>")

    # -- Kintsugi --
    lines.append("")
    lines.append("<b>Kintsugi</b>")
    tel_age = results.get("kintsugi_telemetry_age", "")
    tel_suffix = f" ({tel_age} ago)" if tel_age else ""
    lines.append(f"  {_icon('kintsugi_telemetry')} telemetry{tel_suffix}")
    if "kintsugi_stuck" in results:
        detail = results.get("kintsugi_stuck_detail", "")
        if results["kintsugi_stuck"] is True:
            active = results.get("kintsugi_active_repair")
            if active:
                lines.append(f"  🔄 repairing: {active}")
            else:
                lines.append(f"  {_icon('kintsugi_stuck')} no stuck repairs")
        else:
            lines.append(
                f"  {_icon('kintsugi_stuck')} stuck: {detail}\n"
                "      \u2192 expected &lt;30min; check REST rate limits or CH write latency"
            )
    recent_healed = results.get("kintsugi_recent_healed")
    if recent_healed:
        lines.append(f"  \u2705 recent: {recent_healed}")

    # 24h repair summary — expanded format with explanations
    healed_24h = results.get("kintsugi_healed_24h")
    if healed_24h is not None:
        clean_24h = results.get("kintsugi_clean_24h", 0)
        failed_24h = results.get("kintsugi_failed_24h", 0)
        bars_24h = results.get("kintsugi_bars_24h", "0")

        lines.append("")
        lines.append("\U0001f527 <b>Kintsugi 24h Repair Summary</b>")
        if healed_24h > 0:
            lines.append(f"  \u2705 {healed_24h} gaps healed ({bars_24h} bars written)")
        else:
            lines.append(f"  \u26aa {healed_24h} gaps healed")
        if clean_24h > 0:
            lines.append(f"  \u2705 {clean_24h} shards already clean (no repair needed)")
        if failed_24h > 0:
            lines.append(f"  \u274c {failed_24h} repairs failed")
            lines.append(
                "      \u2192 check: forex symbols (expected), Vision 404, or CH write errors"
            )
        elif healed_24h > 0:
            lines.append("  \u2705 0 failures")
    else:
        # Fallback to legacy compact format
        repairs = results.get("kintsugi_repairs", "")
        bars_24h = results.get("kintsugi_bars_24h", "")
        if repairs:
            bars_suffix = f" | {bars_24h} bars" if bars_24h else ""
            lines.append(f"  {_icon('kintsugi_failures')} 24h: {repairs}{bars_suffix}")
    mem_pct = results.get("kintsugi_memory_pct", "")
    if mem_pct:
        lines.append(f"  {_icon('kintsugi_memory')} memory: {mem_pct}")
    # Shard queue depth
    total_shards = results.get("kintsugi_total_shards")
    if total_shards is not None:
        lines.append(f"  \U0001f4cb queue: shards={total_shards}")

    # -- Freshness (per-symbol, BTCUSDT first) --
    freshness = results.get("symbol_freshness", "")
    if freshness:
        lines.append("")
        lines.append("<b>Freshness</b>")
        for rline in str(freshness).split("\n"):
            lines.append(f"  {rline}")
        if "symbol_needs_backfill" in results:
            lines.append("    \u2192 run: <code>mise run kintsugi:catchup</code>")
        if "symbol_needs_seeding" in results:
            syms = results["symbol_needs_seeding"]
            lines.append(
                f"    \u2192 genesis seeding needed ({syms}):"
                f" <code>populate_cache_resumable(sym, effective_start, end)</code>"
            )

    # -- ClickHouse --
    if "ch_total_bars" in results:
        lines.append("")
        lines.append("<b>ClickHouse</b>")
        bars = results.get("ch_total_bars", "?")
        pairs = results.get("ch_pairs", "?")
        symbols = results.get("ch_symbols", "?")
        db_size = results.get("ch_db_size", "?")
        parts = results.get("ch_parts", "?")
        bars_24h = results.get("ch_bars_24h", "?")
        lines.append(f"  \U0001f4ca {bars} bars | {pairs} pairs | {symbols} symbols")
        lines.append(f"  \U0001f4be {db_size} ({parts} parts)")
        lines.append(f"  \U0001f4c8 {bars_24h} bars/24h")
        freshest = results.get("ch_freshest", "")
        stalest_pairs = results.get("ch_stalest_pairs", "")
        if freshest:
            lines.append(f"  \U0001f7e2 freshest: {freshest}")
        if stalest_pairs:
            lines.append("  \u23f3 stalest:")
            for sline in str(stalest_pairs).split("\n"):
                lines.append(f"    {sline}")
        # Pending mutations and active parts health
        pending = results.get("pending_mutations")
        active_parts_health = results.get("active_parts")
        if pending is not None or active_parts_health is not None:
            mut_icon = (
                "\u2705" if results.get("mutations_healthy") is True else "\u26a0\ufe0f"
            )
            mut_str = pending if pending is not None else "?"
            parts_str = active_parts_health if active_parts_health is not None else "?"
            lines.append(
                f"  {mut_icon} mutations: {mut_str} pending | {parts_str} active parts"
            )

    # -- Stathera Integrity (TELEM-01: unified per-symbol, pipeline/exchange split) --
    if "stathera_overlaps" in results or "stathera_gaps" in results:
        lines.append("")
        lines.append("<b>Stathera</b>")
        overlap_count = results.get("stathera_overlap_count", "0")
        gap_count = results.get("stathera_gap_count", "0")
        overlap_delta = int(results.get("stathera_overlap_delta", "0"))
        gap_delta = int(results.get("stathera_gap_delta", "0"))
        has_overlaps = overlap_count != "0"
        has_gaps = gap_count != "0"

        # Pipeline/exchange gap split (v7.2)
        pipeline_gap_count = results.get("stathera_pipeline_gap_count")
        exchange_gap_count = results.get("stathera_exchange_gap_count")
        has_split = pipeline_gap_count is not None
        if has_split:
            pipeline_gap_delta = int(results.get("stathera_pipeline_gap_delta", "0"))
            exchange_gap_delta = int(results.get("stathera_exchange_gap_delta", "0"))
            has_pipeline_gaps = pipeline_gap_count != "0"
            has_exchange_gaps = exchange_gap_count != "0"

        def _delta_str(delta: int) -> str:
            if delta > 0:
                return f" (+{delta} new)"
            if delta < 0:
                return f" (-{abs(delta)} healed)"
            return ""

        if not has_overlaps and not has_gaps:
            lines.append("  bar-level continuity: clean")
        else:
            # Aggregate summary line with pipeline/exchange split
            summary_parts = []
            if has_overlaps:
                summary_parts.append(
                    f"{overlap_count} overlaps{_delta_str(overlap_delta)}"
                )
            if has_gaps:
                if has_split:
                    summary_parts.append(
                        f"pipeline_gaps={pipeline_gap_count}{_delta_str(pipeline_gap_delta)}, "
                        f"exchange_gaps={exchange_gap_count}{_delta_str(exchange_gap_delta)}"
                    )
                else:
                    # Backward compat: old stathera.py without split
                    summary_parts.append(
                        f"{gap_count} gaps{_delta_str(gap_delta)}"
                    )
            lines.append(f"  {', '.join(summary_parts)}")

            # Reassuring note when all gaps are exchange-level
            if has_split and not has_pipeline_gaps and has_exchange_gaps and not has_overlaps:
                lines.append("  all gaps are exchange-level (permanent, no action needed)")

            # Per-symbol breakdown from stathera_per_symbol
            per_symbol: dict[str, dict] = results.get("stathera_per_symbol", {})
            kintsugi_queue: dict[str, dict] = results.get("stathera_kintsugi_queue", {})
            if per_symbol:
                # Sort by pipeline gaps DESC, then total gaps DESC; show top 5
                sorted_pairs = sorted(
                    per_symbol.items(),
                    key=lambda kv: (
                        -kv[1].get("pipeline_gaps", kv[1].get("gaps", 0)),
                        -kv[1].get("gaps", 0),
                        -kv[1].get("overlaps", 0),
                    ),
                )
                shown = sorted_pairs[:5]
                lines.append("  Per-symbol:")
                for pair_key, counts in shown:
                    queue_info = kintsugi_queue.get(pair_key, {})
                    queue_suffix = ""
                    if queue_info:
                        if queue_info.get("today_only"):
                            queue_suffix = " (today-only, sidecar must fix)"
                        else:
                            pos = queue_info.get("queue_pos")
                            total_q = queue_info.get("total")
                            if pos is not None and total_q is not None:
                                queue_suffix = f" (kintsugi queue #{pos}/{total_q})"
                    # Show pipeline/exchange split per pair if available
                    p_gaps = counts.get("pipeline_gaps")
                    e_gaps = counts.get("exchange_gaps")
                    if p_gaps is not None and e_gaps is not None:
                        gap_detail = f"{p_gaps}p + {e_gaps}x gaps"
                        suffix = " (all exchange)" if p_gaps == 0 and e_gaps > 0 else ""
                    else:
                        gap_detail = f"{counts.get('gaps', 0)} gaps"
                        suffix = ""
                    lines.append(
                        f"    {pair_key}: {gap_detail}, "
                        f"{counts.get('overlaps', 0)} overlaps{suffix}{queue_suffix}"
                    )
                remaining = len(sorted_pairs) - 5
                if remaining > 0:
                    lines.append(f"    + {remaining} more pairs with anomalies")

            # LOUD alert indicator (TELEM-04)
            if results.get("stathera_today_gap_alert"):
                lines.append("  LOUD alert sent for today's new gaps")

            # Fingerprint detail blocks (preserved)
            all_known = results.get("stathera_all_gaps_known", "False") == "True"
            fingerprints: list[dict] = results.get("stathera_gap_fingerprints", [])
            if all_known and fingerprints:
                for fp in fingerprints:
                    cause = fp.get("cause", "")
                    if cause == "pagination_bug_same_ms":
                        dropped = fp.get("dropped_trade_id", "?")
                        ts_ms = fp.get("boundary_ts_ms", "?")
                        sym = fp.get("symbol", "?")
                        thr = fp.get("threshold", "?")
                        lines.append(
                            f"\n  <b>Known root cause</b> ({sym}@{thr}): "
                            f"REST pagination bug (same-millisecond boundary)\n"
                            f"  Rust <code>fetch_aggtrades_rest()</code> advanced "
                            f"<code>startTime</code> by +1ms at page boundary\n"
                            f"  Trade <code>{dropped}</code> "
                            f"(T=<code>{ts_ms}ms</code>) was at the same ms as "
                            f"page-end trade -- silently dropped\n"
                            f"  Kintsugi cannot fix via REST (same bug path). "
                            f"Will self-heal when Binance Vision publishes the "
                            f"day's archive (~24-48h from trade time)\n"
                            f"  No manual action needed -- expected transient"
                        )

    # -- Per-Symbol Health (unified Yesterday + Junction) --
    symbols = get_heartbeat_symbols()
    issues: list[tuple[str, str]] = []  # (symbol, issue_description)
    symbols_checked = 0

    for symbol in symbols:
        symbols_checked += 1
        # Freshness check
        yest = results.get(f"yesterday_{symbol}")
        if yest is False:
            detail = results.get(f"yesterday_{symbol}_detail", "unknown")
            issues.append((symbol, f"freshness: {detail}"))
        elif yest == "query_failed":
            issues.append((symbol, "freshness query failed"))

        # Junction check — only flag if Stathera also shows bar-level gaps.
        # Junction TIDs from /status are startup snapshots; after Puck fills
        # the gap, the bars are contiguous but the snapshot is stale.
        stathera_clean = results.get("stathera_gaps", True) is True
        jdelta = results.get(f"junction_delta_{symbol}")
        if not stathera_clean and jdelta is not None and jdelta not in (0, "partial"):
            detail = results.get(f"junction_detail_{symbol}", f"delta={jdelta}")
            gap_or_overlap = "gap" if jdelta > 0 else "overlap"
            issues.append(
                (symbol, f"junction {gap_or_overlap}={abs(jdelta)} trades ({detail})")
            )
        elif not stathera_clean and jdelta == "partial":
            detail = results.get(f"junction_detail_{symbol}", "")
            issues.append((symbol, f"junction partial: {detail}"))

    junction_available = results.get("junction_available", False)

    lines.append("")
    lines.append("<b>Per-Symbol Health</b>")

    if not issues:
        # All clean -- one summary line
        junc_note = "" if junction_available else " (junction: sidecar unavailable)"
        lines.append(f"  \u2705 {symbols_checked}/{symbols_checked} symbols clean{junc_note}")
    else:
        problem_symbols = len({sym for sym, _ in issues})
        clean_count = symbols_checked - problem_symbols
        lines.append(f"  {clean_count}/{symbols_checked} clean, {len(issues)} issue(s):")
        for sym, desc in issues:
            lines.append(f"    \u274c {sym}: {desc}")
        if not junction_available:
            lines.append("  \u2139\ufe0f junction: sidecar unavailable")

    # -- Checksum Health (v6.0 TELEM-01, exception-only pattern) --
    if "checksum_per_symbol" in results:
        lines.append("")
        lines.append("<b>Checksum Health</b>")
        total_verified = results.get("checksum_total_verified", "0")
        failures_24h = results.get("checksum_failures_24h", "0")
        latest = results.get("checksum_latest", "never")
        failure_details: list[dict] = results.get("checksum_failure_details", [])
        checksum_per_sym: dict[str, dict] = results.get("checksum_per_symbol", {})

        if failures_24h == "0":
            # Clean state: single summary line
            lines.append(
                f"  \u2705 {total_verified} files verified, latest {html.escape(str(latest))}"
                " \u2014 all clean"
            )
        else:
            # Failures present
            lines.append(f"  \u274c {failures_24h} checksum failure(s) in 24h")
            for fd in failure_details:
                sym = html.escape(str(fd.get("symbol", "?")))
                dt = html.escape(str(fd.get("date", "?")))
                exp = html.escape(str(fd.get("expected_hash", "?"))[:16])
                act = html.escape(str(fd.get("actual_hash", "?"))[:16])
                lines.append(f"    \u274c {sym} {dt}: expected {exp}... got {act}...")
            # Per-symbol breakdown for symbols with issues
            failure_symbols = {fd.get("symbol") for fd in failure_details}
            for sym_name, sym_data in checksum_per_sym.items():
                if sym_name in failure_symbols or sym_data.get("verified", 0) == 0:
                    v_count = sym_data.get("verified", 0)
                    last_d = sym_data.get("last_date") or "never"
                    lines.append(
                        f"    {html.escape(sym_name)}: {v_count} verified,"
                        f" last {html.escape(str(last_d))}"
                    )

    # -- System --
    lines.append("")
    lines.append("<b>System</b>")
    free = results.get("disk_free_gb", "?")
    used_pct = results.get("disk_used_pct", "")
    disk_suffix = f" ({used_pct}% used)" if used_pct else ""
    lines.append(f"  {_icon('disk')} disk: {free} GB free{disk_suffix}")
    cb = results.get("circuit_breaker", "n/a")
    lines.append(f"  \U0001f512 breaker: {cb}")
    dl_count = results.get("dead_letter_count", "0")
    if dl_count != "0":
        dl_oldest = results.get("dead_letter_oldest", "?")
        lines.append(f"  \U0001f4ec dead letters: {dl_count} (oldest {dl_oldest})")

    # Rust CH Writer metrics (Issue #318, Phase 37)
    if "ch_writer_bars_flushed" in results:
        lines.append("")
        lines.append("<b>Rust CH Writer</b>")
        ch_flushed = results.get("ch_writer_bars_flushed", "0")
        ch_failed = results.get("ch_writer_bars_failed", "0")
        ch_latency = results.get("ch_writer_latency_ms", "0")
        ch_flush_count = results.get("ch_writer_flush_count", "0")
        ch_dead = results.get("ch_writer_dead_letter_count", "0")
        lines.append(f"  \U0001f4ca bars: {ch_flushed} flushed, {ch_failed} failed")
        lines.append(f"  \u23f1 latency: {ch_latency}ms ({ch_flush_count} flushes)")
        if results.get("ch_writer_dead_letters_ok") is False:
            lines.append(f"  \u274c <b>dead letters: {ch_dead}</b>")
        elif ch_dead != "0":
            lines.append(f"  \u26a0\ufe0f dead letters: {ch_dead}")
        else:
            lines.append(f"  \u2705 dead letters: {ch_dead}")

    # WS error classification (fatal 429/ban vs transient disconnects)
    ws_error_summary = results.get("ws_error_summary", "clean")
    if results.get("ws_errors_healthy") is False:
        lines.append(f"  \u274c <b>FATAL WS: {html.escape(str(ws_error_summary))}</b>")
        lines.append(
            "      \u2192 429/ban = violating Binance limits. "
            "Check: journalctl --user -u opendeviationbar-sidecar --since '10 min ago' | grep -i 'ban\\|429\\|RateLimited'"
        )
    elif results.get("ws_transient_count", "0") != "0":
        ws_transient = results.get("ws_transient_count", "0")
        lines.append(f"  \u2139\ufe0f WS reconnects: {ws_transient} (auto-handled)")

    # -- Resources (last 15 min peaks from Prometheus) --
    cpu_avg = results.get("resource_cpu_avg")
    ram_avg = results.get("resource_ram_used_gb")
    load_avg = results.get("resource_load_avg")
    if cpu_avg or ram_avg or load_avg:
        lines.append("")
        lines.append(f"<b>Resources</b> (last {RESOURCE_WINDOW_MINUTES}m)")
        if cpu_avg:
            cpu_abs = results.get("resource_cpu_abs_peak", "?")
            cpu_typ = results.get("resource_cpu_typ_peak", "?")
            lines.append(
                f"  \U0001f4bb CPU: avg {cpu_avg}% │ ⚡ abs {cpu_abs}% │ \U0001f4ca typ {cpu_typ}%"
            )
        if ram_avg:
            ram_abs = results.get("resource_ram_abs_peak_gb", "?")
            ram_typ = results.get("resource_ram_typ_peak_gb", "?")
            lines.append(
                f"  \U0001f9e0 RAM: avg {ram_avg}G │ ⚡ abs {ram_abs}G │ \U0001f4ca typ {ram_typ}G"
            )
        if load_avg:
            load_abs = results.get("resource_load_abs_peak", "?")
            load_typ = results.get("resource_load_typ_peak", "?")
            lines.append(
                f"  \u26a1 load: avg {load_avg} │ ⚡ abs {load_abs} │ \U0001f4ca typ {load_typ}"
            )

    return "\n".join(lines)
