"""Load a role's system prompt (§16 — prompts are source code) and render the
canon log into a curated digest for the user message (charter §11).

The digest is a projection, not a dump: it surfaces narrative context and
deliberately omits raw integers — companion dispositions render as names only,
luck as its descriptor, and ids/schema_version are dropped (charter §7/§2).
"""

from functools import lru_cache
from pathlib import Path

_PROMPT_DIR = Path(__file__).resolve().parent.parent / "prompts"


@lru_cache(maxsize=None)
def system_prompt(role: str) -> str:
    text = (_PROMPT_DIR / f"{role}.md").read_text(encoding="utf-8")
    # Everything below the first '---' line is the model-facing prompt; the
    # header above it is human/dev front-matter.
    parts = text.split("\n---\n", 1)
    body = parts[1] if len(parts) == 2 else text
    return body.strip()


def render_digest(canon_log: dict) -> str:
    lines: list[str] = []

    location = canon_log.get("location", {})
    lines.append(f"Location: {location.get('name', 'an unknown place')}")

    events = canon_log.get("recent_events", [])
    if events:
        lines.append("Recent events:")
        lines += [f"- {e}" for e in events]

    facts = canon_log.get("established_facts", [])
    if facts:
        lines.append("Established facts:")
        lines += [f"- {f}" for f in facts]

    party = canon_log.get("party", [])
    if party:
        lines.append("Companions present: " + ", ".join(m.get("name", "") for m in party))

    for quest in canon_log.get("active_quests", []):
        if quest.get("status") == "active":
            lines.append(f"Active quest: {quest.get('name', '')} — {quest.get('objective', '')}")

    player = canon_log.get("player", {})
    descriptor = player.get("luck_descriptor")
    if descriptor:
        lines.append(f"Fortune: {descriptor}")
    lines.append(f"Player: {player.get('name', '')}, a {player.get('class_id', '')}")

    lines.append("")
    lines.append("Describe the scene as it is now.")
    return "\n".join(lines)
