"""Self-contained, print-friendly HTML report written into every result bundle."""
from __future__ import annotations

import html
from pathlib import Path

STATUS_COLOR = {"pass": "#1baf7a", "warn": "#eda100", "fail": "#e34948", "info": "#2a78d6", "skipped": "#8a8a8a"}


def _fmt(v):
    if isinstance(v, float):
        return f"{v:.3f}"
    return html.escape("" if v is None else str(v))


def _table(rows, cols):
    if not rows:
        return "<p class=muted>None.</p>"
    head = "".join(f"<th>{html.escape(c)}</th>" for c in cols)
    body = "".join("<tr>" + "".join(f"<td>{_fmt(r.get(c))}</td>" for c in cols) + "</tr>" for r in rows)
    return f"<table><thead><tr>{head}</tr></thead><tbody>{body}</tbody></table>"


def write_report_html(res: dict, path: Path) -> None:
    s = res["summary"]
    diags = "".join(
        f"<div class=diag><span class=badge style='background:{STATUS_COLOR[d['status']]}'>{d['status']}</span>"
        f"<h3>{html.escape(d['title'])}</h3><p class=head>{html.escape(d['headline'])}</p>"
        f"<p>{html.escape(d['detail'])}</p><p><b>For model building:</b> {html.escape(d['ml_implication'])}</p>"
        + (f"<p class=muted>{html.escape(d['caveat'])}</p>" if d["caveat"] else "") + "</div>"
        for d in res["diagnostics"])
    recs = "".join(f"<li><b>{html.escape(r['title'])}</b> (<code>{html.escape(r['file'])}</code>): "
                   f"{html.escape(r['text'])}</li>" for r in res["recommendations"])
    sections = [
        ("Negative-set balance", _table(res["balance"], ["negative_set", "n_negatives", "positive_mean", "negative_mean", "smd", "ks_statistic", "length_smd"])),
        ("Splits and leakage gates", _table(res["splits"], ["regime", "train_pairs", "test_pairs", "train_proteins", "test_proteins", "protein_overlap", "test_components", "passed"])),
        ("Protein-novelty curve", _table(res["novelty"], ["representation", "regime", "model", "test_pairs", "roc_auc", "pr_auc", "mcc"])),
        ("Topology-only and length-only controls", _table([r for r in res["topology"] if r["model"] == "lr"], ["feature", "evaluated_on", "roc_auc", "pr_auc", "mcc"])),
        ("Consistent-negative revalidation", _table(res["revalidation"], ["representation", "regime", "negative_set", "test_pairs", "roc_auc", "pr_auc", "mcc"])),
        ("Component-aware uncertainty (R3)", _table(res["uncertainty"], ["representation", "negative_set", "n_test", "n_components", "roc_auc", "boot_low", "boot_high", "jack_low", "jack_high", "boot_p_bh", "jack_p_bh"])),
    ]
    if res.get("species"):
        sp = res["species"]
        sections += [("Species composition", _table(sp["composition"], ["species", "proteins", "positive_within", "negative_within", "positive_cross", "negative_cross"])),
                     ("Cross-species fraction", _table(sp["cross_species"], ["set", "n_pairs", "cross_species", "cross_species_fraction"])),
                     ("Same-species shortcut", _table(sp["same_species_shortcut"], ["evaluated_on", "n_evaluated", "roc_auc"])),
                     ("Within-species controls", _table(sp["within_metrics"], ["species", "negative_set", "representation", "model", "test_pairs", "roc_auc", "pr_auc"]))]
    body = "".join(f"<section><h2>{html.escape(t)}</h2>{c}</section>" for t, c in sections)
    doc = f"""<!doctype html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1">
<title>PPI Benchmark Report</title><style>
:root{{--ink:#1d1b18;--paper:#faf7f0;--muted:#6b665d;--line:#e2dccf}}
body{{margin:0;background:var(--paper);color:var(--ink);font:15px/1.55 Georgia,'Times New Roman',serif}}
main{{max-width:960px;margin:0 auto;padding:40px 20px}}h1{{font-size:34px;margin:0 0 4px}}h2{{margin-top:36px;border-bottom:1px solid var(--line);padding-bottom:6px}}
.verdict{{font-size:22px;margin:18px 0 6px}}.muted{{color:var(--muted);font-size:13px}}
.diag{{border:1px solid var(--line);border-radius:10px;padding:12px 16px;margin:12px 0;background:#fff}}
.diag h3{{display:inline;margin-left:8px;font-size:17px}}.head{{font-weight:bold}}
.badge{{color:#fff;border-radius:99px;padding:2px 10px;font:12px/1.6 ui-monospace,monospace;text-transform:uppercase}}
table{{border-collapse:collapse;width:100%;font:12px/1.4 ui-monospace,Menlo,monospace;overflow-x:auto;display:block}}
th,td{{border-bottom:1px solid var(--line);padding:4px 8px;text-align:right}}th:first-child,td:first-child{{text-align:left}}
</style></head><body><main>
<h1>PPI benchmark evaluation</h1>
<p class=muted>PPI Benchmark Studio · engine {res['engine_version']} (framework {res['framework_version']}) · {res['generated_at']} · seed {res['config']['seed']} · preset {res['config']['preset']}</p>
<p class=verdict><b>{html.escape(s['verdict'])}</b> — {html.escape(s['headline'])}</p>
<p class=muted>Readiness score {s['score']}/100. {html.escape(s['score_note'])}</p>
<h2>Diagnostics</h2>{diags}
<h2>Recommendations</h2><ul>{recs}</ul>
{body}
<h2>Methods</h2><p>{html.escape(res['methods_text'])}</p>
</main></body></html>"""
    Path(path).write_text(doc)
