"""Fill audit_outreach_template.pptx from prospects.csv: one deck (+ PDF + PNG snapshot) per prospect.
Usage: python3 fill_template.py [prospects.csv]   -> output/prospects/<slug>/
Swaps every [Token] run, sizes score bars, colours RAG bars and impact/effort pills, and sets the score ring."""
import csv, re, sys, subprocess, shutil
from pathlib import Path
from pptx import Presentation
from pptx.util import Emu
from pptx.chart.data import CategoryChartData
from pptx.dml.color import RGBColor
H = Path(__file__).parent; TPL = H / "output/audit_outreach_template.pptx"
rgb = lambda h: RGBColor.from_string(h)
RAG = lambda v: "2E7D5B" if v >= 75 else ("D99A2B" if v >= 50 else "B5413A")
PILL = {"impact": {"High": "B5413A", "Medium": "D99A2B", "Low": "2E7D5B"}, "effort": {"High": "0B2545", "Medium": "D99A2B", "Low": "1A7F86"}}
BAR_W = None

def frames(shapes):
    for sh in shapes:
        if sh.has_text_frame: yield sh.text_frame
        if getattr(sh, "has_table", False) and sh.has_table:
            for r in sh.table.rows:
                for c in r.cells: yield c.text_frame

def fill(row, out):
    prs = Presentation(TPL); left = set()
    for slide in prs.slides:
        for tf in frames(slide.shapes):
            for p in tf.paragraphs:
                for r in p.runs:
                    for tok in re.findall(r"\[([^\]]+)\]", r.text):
                        if tok in row: r.text = r.text.replace(f"[{tok}]", row[tok])
                        else: left.add(tok)
        for sh in slide.shapes:
            if sh.name.startswith("bar:"):
                v = float(row[sh.name[4:]]); sh.width = Emu(int(Emu(3657600) * max(v, 4) / 100))  # track = 4.0in
                sh.fill.solid(); sh.fill.fore_color.rgb = rgb(RAG(v))
            elif sh.name.startswith("pill:"):
                key = sh.name[5:].split()[0].lower(); val = row[sh.name[5:]]
                sh.fill.solid(); sh.fill.fore_color.rgb = rgb(PILL[key].get(val, "5B6776"))
            elif sh.name == "gauge":
                v = float(row["Score"]); cd = CategoryChartData(); cd.categories = ["score", "rest"]; cd.add_series("Score", [v, 100 - v])
                sh.chart.replace_data(cd)
                sh.chart.plots[0].series[0].points[0].format.fill.solid()
                sh.chart.plots[0].series[0].points[0].format.fill.fore_color.rgb = rgb(RAG(v) if v < 75 else "1A7F86")
    if left: raise SystemExit(f"unfilled tokens: {sorted(left)}")
    out.parent.mkdir(parents=True, exist_ok=True); prs.save(out); return out

def export(pptx):
    d = pptx.parent
    subprocess.run(["soffice", "--headless", "--convert-to", "pdf", "--outdir", str(d), str(pptx)], check=True, capture_output=True)
    pdf = pptx.with_suffix(".pdf"); sl = d / "slides"; shutil.rmtree(sl, ignore_errors=True); sl.mkdir()
    subprocess.run(["pdftoppm", "-png", "-scale-to-x", "1600", "-scale-to-y", "900", str(pdf), str(sl / "slide")], check=True)
    shutil.copy(sl / "slide-2.png", d / "email-snapshot.png")

if __name__ == "__main__":
    src = Path(sys.argv[1]) if len(sys.argv) > 1 else H / "prospects.csv"
    for row in csv.DictReader(open(src, encoding="utf-8")):
        slug = re.sub(r"[^a-z0-9]+", "-", row["Prospect name"].lower()).strip("-")
        p = fill(row, H / "output/prospects" / slug / f"{slug}_audit_outreach.pptx"); export(p); print("built", p.relative_to(H))
