#!/usr/bin/env python3
import json, os
from weasyprint import HTML
d=json.load(open("deep.json"))
B=d['prog']['basis']; R=d['prog']['repr']
base=os.getcwd()
def img(n): return f"file://{base}/{n}"
def eur(x): return f"{x:,.2f}".replace(",","X").replace(".",",").replace("X",".")
def de(x,dec=1): return (f"{x:,.{dec}f}").replace(",","X").replace(".",",").replace("X",".")
order=['Material','Labor','Manufacturing','ScrapB','SGA','Profit']
nm={'Material':'Material','Labor':'Labor','Manufacturing':'Manufacturing','ScrapB':'Scrap','SGA':'SG&A','Profit':'Profit'}
rows="".join(
 f"<tr><td>{nm[k]}</td><td class='n'>{eur(B[k])}</td><td class='n'>{B['_pct'][k]:.0f}%</td>"
 f"<td class='n'>{eur(R[k])}</td><td class='n'>{R['_pct'][k]:.0f}%</td>"
 f"<td class='n {'pos' if R[k]>B[k] else 'neg'}'>{(R[k]/B[k]-1)*100:+.0f}%</td></tr>"
 for k in order)
salesrow=f"<tr class='tot'><td>Sales (Angebotspreis)</td><td class='n'>{eur(B['Sales'])}</td><td class='n'>100%</td><td class='n'>{eur(R['Sales'])}</td><td class='n'>100%</td><td class='n pos'>+31,5%</td></tr>"
yrs=d['years']; vol=d['volume']; ann=d['annual']
yrows="".join(f"<tr><td>{y}</td><td class='n'>{de(v,0)}</td><td class='n'>{de(a/1e6,2)}</td></tr>" for y,v,a in zip(yrs,vol,ann))
tot_ann=sum(ann)

html=f"""<!doctype html><html><head><meta charset='utf-8'><style>
@page {{ size:A4; margin:11mm 12mm; }}
*{{font-family:'Inter','DejaVu Sans',Arial,sans-serif;box-sizing:border-box}}
body{{color:#1a2227;font-size:9pt;line-height:1.35}}
h1{{font-size:16pt;color:#037493;margin:0}}
.sub{{color:#5b6b73;font-size:8pt;margin:2px 0 0}}
.bar{{height:3px;background:#037493;margin:7px 0 10px;border-radius:2px}}
h2{{font-size:11pt;color:#037493;margin:12px 0 5px;border-bottom:1px solid #d7e3e7;padding-bottom:2px}}
img{{width:100%;border:1px solid #eef2f3;border-radius:4px}}
.half{{display:flex;gap:9px;align-items:flex-start}} .half img{{width:58%}} .half table{{width:42%}}
table{{width:100%;border-collapse:collapse;font-size:8.4pt;margin:3px 0}}
th{{background:#037493;color:#fff;text-align:left;padding:4px 6px}}
td{{padding:3px 6px;border-bottom:1px solid #e9eef0}}
td.n{{text-align:right;font-variant-numeric:tabular-nums}}
.pos{{color:#c0392b;font-weight:600}} .neg{{color:#1e8449;font-weight:600}}
.tot{{font-weight:700;background:#eef6f8}}
.para{{background:#eef6f8;border-left:3px solid #037493;padding:7px 10px;border-radius:0 4px 4px 0;margin:5px 0}}
.foot{{margin-top:10px;font-size:7.2pt;color:#90a0a6;border-top:1px solid #e6edef;padding-top:5px}}
</style></head><body>

<h1>BMW QAF G60 DP — Kostenstruktur, Produktion &amp; Einsparpotenzial</h1>
<p class="sub">Basis (24Q4) vs RePricing (26Q1) · 111 Positionen · Werte je Fahrzeugsatz (Σ aller Positionen) · SupplierPulse</p>
<div class="bar"></div>

<div class="para"><b>Kernaussage:</b> Der Angebotspreis steigt +31,5 % — getrieben von Maschinen-Stundensatz (+195 %), neuem Ineffizienz-Aufschlag (+55 %) und verdoppelten Zuschlägen. <b>Die Produktion selbst ist unverändert:</b> Cycle time und Mitarbeiterzahl bleiben in fast allen Positionen gleich. Material wird sogar günstiger (−2 %), verliert aber Anteil (69 % → 52 %).</div>

<h2>1 · Kostenstruktur (Material · Labor · Manufacturing · Scrap · SG&amp;A · Profit · Sales)</h2>
<table>
<tr><th>Bucket</th><th>Basis €</th><th>Basis %</th><th>RePr €</th><th>RePr %</th><th>Δ %</th></tr>
{rows}{salesrow}
</table>
<img src="{img('c1_kostenstruktur.png')}"/>

<h2>2 · Woher der Anstieg kommt</h2>
<img src="{img('c2_waterfall.png')}"/>

<h2>3 · Produktionssicht — Raten rauf, Prozess unverändert</h2>
<img src="{img('c4_produktion.png')}"/>
<p class="sub">Cycle time [s], Parts/Cycle und Anzahl direkter Mitarbeiter sind in ~96 % der Positionen identisch. Verändert: Maschinen-Stundensatz ×2,95, Ineffizienz-Aufschlag 0 → 55 %, Scrap je Prozess-Schritt 2 % → 3 %.</p>

<h2>4 · Größte Preistreiber je Bauteil</h2>
<img src="{img('c3_topmover.png')}"/>

<h2>5 · Hochrechnung über die Programmlaufzeit (Stückzahlen aus QAF)</h2>
<div class="half"><img src="{img('c5_jahre.png')}"/>
<table>
<tr><th>Jahr</th><th>Volumen</th><th>Mehrk. M€</th></tr>
{yrows}
<tr class="tot"><td>Σ Laufzeit</td><td class="n">{de(sum(vol),0)}</td><td class="n">{de(tot_ann/1e6,1)}</td></tr>
</table></div>
<p class="sub">Δ {eur(d['dset'])} € je Fahrzeugsatz × Jahresvolumen. <b>Obergrenze</b> (Annahme: alle Positionen je Fahrzeug) — variantenscharf in der App niedriger. Zeigt die Größenordnung des Verhandlungshebels: jede abgewehrte Erhöhung skaliert mit ~1,55 Mio Fahrzeugen.</p>

<div class="foot">Quelle: 100 - G60_DP_QAF_Basis_24_10_BMW.xlsm · 20260508_BMW QAF_G60_DP_RePricing_HO.xlsm · Stückzahlen-Sheet. Vertraulich — Lieferanten-Kalkulationsdaten. Erstellt durch SupplierPulse / Aria.</div>
</body></html>"""
open("dashboard.html","w").write(html)
HTML(string=html).write_pdf("QAF_Dashboard_G60_DP.pdf")
print("dashboard PDF written")
