"""Export the discovery notebook as an LLM-readable report source.

Executes the notebook ONCE (widget defaults — or whatever you've captured
and saved in the notebook), then converts the executed copy twice:

  exports/cx_discovery.html  — human-reviewable, full presentation
  exports/cx_discovery.md    — leanest LLM input: presentation-tagged cells
                               (setup, widgets, board) are stripped, a
                               framing preamble is prepended, and the data
                               appendix ends the file with one fenced JSON
                               block — the machine source of truth.

Engagement identity (client, date, facilitator) is read from the notebook's
``engagement-data`` cell and stamped into the preamble.

Run from the study root:  python scripts/export_report.py
"""
from __future__ import annotations

import subprocess
import sys
import tempfile
from pathlib import Path
from typing import Any

ROOT = Path(__file__).resolve().parent.parent
NOTEBOOK = ROOT / "notebooks" / "cx_discovery.ipynb"
EXPORTS = ROOT / "exports"

# Cells tagged with any of these never reach the .md export — they are
# stage presentation (source and widget-repr noise), not session record.
STRIP_TAGS_FROM_MD = '{"presentation"}'


def engagement_data() -> dict[str, Any]:
    """Exec the engagement-data cell (same trick as tests/conftest.py)."""
    import nbformat

    nb = nbformat.read(NOTEBOOK, as_version=4)
    cells = [c for c in nb.cells
             if "engagement-data" in c.metadata.get("tags", [])]
    assert len(cells) == 1, "expected exactly one engagement-data cell"
    ns: dict[str, Any] = {}
    exec(compile(cells[0].source, f"{NOTEBOOK.name} [engagement-data]", "exec"), ns)
    return ns["ENGAGEMENT"]  # type: ignore[no-any-return]


def preamble() -> str:
    eng = engagement_data()
    who = " · ".join(str(eng[k]).strip()
                     for k in ("client", "workshop_date", "facilitator")
                     if str(eng.get(k, "")).strip())
    attendees = ", ".join(str(a) for a in eng.get("attendees", ()) or ())
    if who:
        line = who + (f" — attendees: {attendees}" if attendees else "")
    else:
        line = "master copy — placeholders; no engagement captured."
    return "\n".join([
        "<!-- Export preamble — generated by scripts/export_report.py -->",
        "**What this is** — the exported record of a CX Exploration & Discovery",
        "workshop session, produced from the Mercury-served notebook that ran the",
        "session. It is LLM input for drafting the survey write-up or seeding a",
        "business case.",
        "",
        f"**Engagement** — {line}",
        "",
        "**How to read it** — first the workshop content as annotated source (the",
        "topic bank, then the engagement data), then the facilitation script",
        "(every prompt, grouped by topic and sub-topic), the verification gate,",
        "and finally the captured-session record: the per-topic table (status,",
        "covered sub-topics, notes) and — last — **Session state (JSON)**, one",
        "fenced `json` block. Where prose and JSON disagree, the JSON block is",
        "the source of truth.",
        "",
        "---",
        "",
        "",
    ])


def main() -> None:
    if len(sys.argv) > 1 and sys.argv[1] not in NOTEBOOK.name:
        sys.exit(f"no notebook matches {sys.argv[1]!r}")
    EXPORTS.mkdir(exist_ok=True)

    with tempfile.TemporaryDirectory() as tmp:
        executed = Path(tmp) / NOTEBOOK.name
        # 1. Execute once — both formats convert the same session state.
        # (Never combine --execute with TagRemovePreprocessor in one call:
        # the cell could be stripped before it runs.)
        subprocess.run(
            [sys.executable, "-m", "nbconvert", "--execute",
             "--to", "notebook", "--output", str(executed), str(NOTEBOOK)],
            check=True, cwd=ROOT,
        )
        # 2. HTML — full presentation, human review artifact.
        subprocess.run(
            [sys.executable, "-m", "nbconvert", "--to", "html",
             "--output-dir", str(EXPORTS), "--output", NOTEBOOK.stem,
             str(executed)],
            check=True, cwd=ROOT,
        )
        # 3. Markdown — LLM artifact: strip presentation cells.
        subprocess.run(
            [sys.executable, "-m", "nbconvert", "--to", "markdown",
             "--output-dir", str(EXPORTS), "--output", NOTEBOOK.stem,
             "--TagRemovePreprocessor.enabled=True",
             f"--TagRemovePreprocessor.remove_cell_tags={STRIP_TAGS_FROM_MD}",
             str(executed)],
            check=True, cwd=ROOT,
        )

    # 4. Prepend the framing preamble to the markdown export.
    md = EXPORTS / f"{NOTEBOOK.stem}.md"
    md.write_text(preamble() + md.read_text(encoding="utf-8"), encoding="utf-8")

    for p in sorted(EXPORTS.iterdir()):
        if p.suffix in (".html", ".md"):
            print(f"wrote {p.relative_to(ROOT)} ({p.stat().st_size / 1024:,.0f} KB)")


if __name__ == "__main__":
    main()
