from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.lib.units import cm
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak, KeepTogether
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
from reportlab.lib.colors import HexColor
from pathlib import Path

OUT = Path('/home/agent/tmp/schulraumplanung_260708/Sitzungsvorbereitung_Schulraumplanung_Windisch_FDP_260708.pdf')

pdfmetrics.registerFont(TTFont('NotoSans', '/usr/share/fonts/truetype/noto/NotoSans-Regular.ttf'))
pdfmetrics.registerFont(TTFont('NotoSans-Bold', '/usr/share/fonts/truetype/noto/NotoSans-Bold.ttf'))

PRIMARY = HexColor('#004B8D')  # sober blue
DARK = HexColor('#1f2937')
LIGHT = HexColor('#EAF2FB')
MID = HexColor('#BFD7EF')
GREEN = HexColor('#0B7A3B')
ORANGE = HexColor('#B45309')
RED = HexColor('#B91C1C')
GREY = HexColor('#F3F4F6')

styles = getSampleStyleSheet()
styles.add(ParagraphStyle(name='TitleN', fontName='NotoSans-Bold', fontSize=22, leading=27, textColor=PRIMARY, alignment=TA_CENTER, spaceAfter=12))
styles.add(ParagraphStyle(name='SubTitleN', fontName='NotoSans', fontSize=11, leading=15, textColor=DARK, alignment=TA_CENTER, spaceAfter=8))
styles.add(ParagraphStyle(name='H1N', fontName='NotoSans-Bold', fontSize=15, leading=19, textColor=PRIMARY, spaceBefore=12, spaceAfter=8))
styles.add(ParagraphStyle(name='H2N', fontName='NotoSans-Bold', fontSize=12.5, leading=16, textColor=DARK, spaceBefore=9, spaceAfter=5))
styles.add(ParagraphStyle(name='BodyN', fontName='NotoSans', fontSize=9.2, leading=12.2, textColor=DARK, spaceAfter=5))
styles.add(ParagraphStyle(name='SmallN', fontName='NotoSans', fontSize=7.8, leading=10, textColor=colors.HexColor('#4b5563')))
styles.add(ParagraphStyle(name='BulletN', fontName='NotoSans', fontSize=8.9, leading=11.5, leftIndent=11, firstLineIndent=-7, spaceAfter=3))
styles.add(ParagraphStyle(name='CalloutN', fontName='NotoSans-Bold', fontSize=10, leading=13, textColor=DARK, backColor=LIGHT, borderColor=MID, borderWidth=0.5, borderPadding=7, spaceBefore=5, spaceAfter=8))
styles.add(ParagraphStyle(name='FooterN', fontName='NotoSans', fontSize=7, textColor=colors.HexColor('#6b7280'), alignment=TA_CENTER))


def P(txt, style='BodyN'):
    return Paragraph(txt, styles[style])


def bullets(items):
    story=[]
    for item in items:
        story.append(P('• ' + item, 'BulletN'))
    return story


def kv_table(rows, widths=None):
    data = [[P(f'<b>{a}</b>', 'BodyN'), P(b, 'BodyN')] for a,b in rows]
    t=Table(data, colWidths=widths or [4.2*cm, 11.2*cm], hAlign='LEFT')
    t.setStyle(TableStyle([
        ('FONTNAME',(0,0),(-1,-1),'NotoSans'),
        ('VALIGN',(0,0),(-1,-1),'TOP'),
        ('BACKGROUND',(0,0),(0,-1),LIGHT),
        ('GRID',(0,0),(-1,-1),0.25,colors.HexColor('#d1d5db')),
        ('LEFTPADDING',(0,0),(-1,-1),5),('RIGHTPADDING',(0,0),(-1,-1),5),
        ('TOPPADDING',(0,0),(-1,-1),4),('BOTTOMPADDING',(0,0),(-1,-1),4),
    ]))
    return t


def normal_table(headers, rows, widths, header_bg=PRIMARY):
    data = [[P(f'<b>{h}</b>', 'SmallN') for h in headers]] + [[P(str(c), 'SmallN') for c in row] for row in rows]
    t=Table(data, colWidths=widths, repeatRows=1, hAlign='LEFT')
    t.setStyle(TableStyle([
        ('BACKGROUND',(0,0),(-1,0),header_bg),
        ('TEXTCOLOR',(0,0),(-1,0),colors.white),
        ('FONTNAME',(0,0),(-1,0),'NotoSans-Bold'),
        ('VALIGN',(0,0),(-1,-1),'TOP'),
        ('GRID',(0,0),(-1,-1),0.25,colors.HexColor('#d1d5db')),
        ('ROWBACKGROUNDS',(0,1),(-1,-1),[colors.white, GREY]),
        ('LEFTPADDING',(0,0),(-1,-1),4),('RIGHTPADDING',(0,0),(-1,-1),4),
        ('TOPPADDING',(0,0),(-1,-1),3),('BOTTOMPADDING',(0,0),(-1,-1),3),
    ]))
    return t


def footer(canvas, doc):
    canvas.saveState()
    canvas.setFont('NotoSans', 7)
    canvas.setFillColor(colors.HexColor('#6b7280'))
    canvas.drawString(1.6*cm, 0.9*cm, 'Sitzungsvorbereitung Schulraumplanung Windisch – FDP-Perspektive')
    canvas.drawRightString(19.4*cm, 0.9*cm, f'Seite {doc.page}')
    canvas.setStrokeColor(MID)
    canvas.line(1.6*cm, 1.15*cm, 19.4*cm, 1.15*cm)
    canvas.restoreState()

story=[]
story.append(P('Sitzungsvorbereitung<br/>Schulraumplanung Windisch', 'TitleN'))
story.append(P('Begleitgruppe vom 08. Juli 2026 · FDP-Perspektive · kompakte Entscheidungs- und Fragenbasis', 'SubTitleN'))
story.append(Spacer(1, 0.5*cm))
story.append(P('Kurzfazit', 'H1N'))
story.append(P('Der Bericht Phase 1+2 ist als fachliche Grundlage plausibel und zeigt echten Handlungsbedarf. Aus FDP-Sicht sollte Phase 3 unterstützt werden – aber nur mit klaren Leitplanken: Variantenvergleich, Kostentransparenz, Etappierung, Betriebskosten/Personalfolgen, Priorisierung und robuste Annahmen. Kein Blankoscheck für einen später kaum steuerbaren Ausbau.', 'CalloutN'))
story.append(kv_table([
    ('Sitzung', 'Mittwoch, 08.07.2026, 18:00–20:00, Gemeindehaus Windisch, 8. Stock, Einwohnerratssaal'),
    ('Hauptdokument', 'Schulraumplanung Windisch, Bericht Phase 1+2, Kontextplan, 01.06.2026, 89 Seiten'),
    ('Beilagen', 'Schemapläne, Raumverzeichnisse nach Schulstufe/Gebäude, Raumkarten Zyklus 1/2 und 3, pädagogisches Konzept, Begehungsprotokoll'),
    ('Entscheidlogik', 'Phase 1+2 = Bedarf und Grundlagen; Phase 3 = Variantenstudium und Lösungskonzeption mit Nutzwertanalyse/Grobkosten'),
]))

story.append(P('1. Wichtigste gesicherte Fakten aus dem Bericht', 'H1N'))
story.append(normal_table(['Thema', 'Aussage aus Bericht', 'FDP-Einordnung'], [
    ('Bevölkerung', 'Mit Stadtraum Bahnhof ca. 8’200 → 12’800 Einwohner in 20 Jahren; ohne Stadtraum Bahnhof ca. 10’850.', 'Planung muss Wachstum ernst nehmen, aber Stadtraum-Annahmen separat und politisch belastbar klären.'),
    ('KiGa/Primar SuS', 'Mit Stadtraum Bahnhof ca. 700 → 1’100 SuS; ohne Stadtraum Bahnhof ca. 700 → 900 SuS.', 'Grosser Unterschied: Dimensionierung darf nicht implizit doppelt zählen oder falsche Zuständigkeit übernehmen.'),
    ('Kindergarten', 'Heute 8 Klassen; mittelfristig 9–11 Klassen, Spitze abhängig von «Im Winkel» und Geburtenrate.', 'Schulwege und dezentrale Standorte wichtiger als reine Klassenzahl.'),
    ('Primarschule', 'Heute 25 Klassen; langfristig ca. 30 Klassen. Hauptdruck auf Dohlenzelg / «Im Winkel».', 'Priorität auf realen Engpassstandort, nicht flächendeckende Wunschliste.'),
    ('Oberstufe', 'Bez bald 12; Real langfristig 9; Sek langfristig bis 9. Bei Lupfig/Birrhard deutlich mehr Druck.', 'Einzugsgebiet ist politischer Vorentscheid mit grosser Kostenwirkung.'),
    ('Raumqualität', 'Bestand trägt Betrieb rechnerisch, erfüllt pädagogische/organisatorische Anforderungen aber nur teilweise.', 'Gute Differenzierung: Nicht jeder rechnerische m²-Überschuss ist nutzbar.'),
], [2.8*cm, 7.0*cm, 5.8*cm]))

story.append(P('2. Defizite und Handlungsfelder', 'H1N'))
story.append(normal_table(['Bereich', 'Defizit / Aussage', 'Was kritisch ist'], [
    ('Kindergarten', 'SOLL 1: 3 Gruppenräume + 4 Förderräume fehlen. SOLL 2: zusätzlich 2 Unterrichtsräume, 5 Gruppenräume, 4 Förderräume fehlen.', 'Nicht vorschnell neu bauen; zuerst Standort, Sanierungszustand und Schulwege klären.'),
    ('Primarschule', 'SOLL 1: 3 Gruppenräume, 4 Förderräume, 1 Aula/Diversraum fehlen. SOLL 2: 8 Unterrichtsräume, 5 Gruppenräume, 4 Förderräume, 1 Aula fehlen.', 'Dohlenzelg priorisieren; Rütenen/Dorf nicht automatisch auf Maximalstandard ausbauen.'),
    ('Oberstufe', 'Gruppenräume, Förderung, Aula/Aufenthalt fehlen; Unterrichtsräume rechnerisch eher ausreichend.', 'Qualitative Optimierung statt blindem Klassenzimmerausbau.'),
    ('Tagesstruktur', 'Heute ca. 507 m²; Szenarien künftig ca. 1’002–3’462 m².', 'Grösster politischer Hebel. Ohne Angebotsentscheid keine seriöse Bauplanung.'),
    ('Bibliothek', 'Bedarf je Berechnung ca. 390–695 m²; heutige Fläche zu klein.', 'Gemeinde-/Schulbibliothek ist Service public, aber Grösse/Standort müssen kostenbewusst entschieden werden.'),
    ('Musikschule/SSA', 'Dezentrale Räume, geschützte Gesprächsräume, Instrumentenlager und Infrastruktur fehlen teilweise.', 'Synergien nutzen, Exklusivflächen begrenzen, Betriebskonzept verlangen.'),
], [2.6*cm, 7.0*cm, 6.0*cm]))

story.append(PageBreak())
story.append(P('3. Fragwürdige oder besonders prüfbedürftige Annahmen', 'H1N'))
story.append(P('Die folgenden Punkte sind nicht zwingend falsch, aber politisch und finanziell so relevant, dass sie vor Phase 3 aktiv verifiziert werden müssen.', 'BodyN'))
story.append(normal_table(['Annahme', 'Warum kritisch?', 'Frage / Auftrag'], [
    ('Stadtraum Bahnhof separat', 'Der Bericht rechnet offenbar damit, dass Stadtraum Bahnhof eigene KiGa-/Primarlösung erhält. Wenn das nicht kommt oder später kommt, verschiebt sich grosser Bedarf in den Bestand.', 'Welche verbindlichen Annahmen gibt es zu eigener Schule/KiGa im Stadtraum? Wer finanziert, wann, mit welchem Perimeter?'),
    ('Areal «Im Winkel» zeitlich geballt', 'Die KiGa-Spitze von 11 Klassen hängt stark davon ab. Langsamere Entwicklung senkt/verschiebt Spitze.', 'Welche Realisierungswahrscheinlichkeit und Etappierung sind aktuell? Sensitivität in Varianten darstellen.'),
    ('Geburtenrate konstant ca. 0.93%', 'Der Bericht zeigt: kleine Änderungen verändern Klassenbedarf deutlich.', 'Jährliche Aktualisierung als Planungsmechanismus; keine irreversible Überdimensionierung.'),
    ('Tagesstruktur-Szenario', 'Bandbreite 1’002–3’462 m² ist enorm; politische Zielsetzung fehlt.', 'Gemeinderat soll vor Variantenstudium Angebotsniveau definieren: tief/mittel/hoch/Tagesschule.'),
    ('Oberstufe Nachbargemeinden', 'Lupfig/Birrhard erhöhen Raumdruck massiv.', 'Kein Raumprogramm ohne geklärte Verträge, Kostenteilung und Schülerprognosen.'),
    ('Gebäudezustand separat', 'Zustand war nicht Bestandteil der Schulraumplanung, entscheidet aber über Sanieren/Ersatz/Provisorien.', 'Zustands- und Investitionsplan als Pflichtinput für Phase 3.'),
    ('Pädagogischer Standard 1 Gruppenraum pro 2 Klassenzimmer', 'Pädagogisch plausibel, aber kosten- und flächenwirksam.', 'Priorisierung: Muss, Soll, Kann – und welche Mehrfachnutzungen sind realistisch?'),
    ('Berichtsstatus', 'Dokument enthält Hinweis «Gelb = noch zu ergänzen»; einzelne OCR/Tabellen zeigen Entwurfscharakter.', 'Vor politischer Freigabe finale, bereinigte Version mit klarer Beschlussfassung verlangen.'),
], [3.0*cm, 6.2*cm, 6.4*cm]))

story.append(P('4. Risiken aus FDP-Sicht', 'H1N'))
story.append(normal_table(['Risiko', 'Beschreibung', 'Gegenmassnahme'], [
    ('Kosten- und Scope-Creep', 'Aus pädagogischen Wünschen, Tagesstruktur, Bibliothek, Musikschule, Vereinen und Reserven kann ein Maximalprojekt entstehen.', 'Klare Priorisierung: zwingend / zweckmässig / wünschbar; Varianten mit Investitions- und Betriebskosten.'),
    ('Überdimensionierung', 'Prognosen sind sensitiv auf Geburtenrate, Arealentwicklung und Einzugsgebiete.', 'Etappierung, modulare Erweiterungen, Reserven statt sofortigem Vollausbau.'),
    ('Betriebskosten unterschätzt', 'Tagesstruktur/Mittagstisch braucht Räume plus Personal, Aufsicht, Reinigung, Unterhalt.', 'Lebenszyklus- und Betriebskosten je Variante ausweisen.'),
    ('Falsche Standortentscheide', 'Neubau oder Sanierung am falschen Standort bindet Mittel über Jahrzehnte.', 'Standortstrategie vor Objektplanung; Schulwege, Zustand, Synergien und Wachstum gewichten.'),
    ('Provisorien / Verzögerungen', 'Wenn Phase 3 zu spät oder unklar startet, drohen teure Übergangslösungen.', 'Zeitplan mit Meilensteinen, Entscheidfenstern und Provisorienstrategie.'),
    ('Unklare Drittgemeinden', 'Oberstufen-Schüler aus anderen Gemeinden können Kapazität und Kosten stark beeinflussen.', 'Vertragliche Grundlagen und Kostenteiler vor Dimensionierung.'),
], [3.0*cm, 6.2*cm, 6.4*cm]))

story.append(P('5. Chancen', 'H1N'))
story.extend(bullets([
    'Schulraumplanung kann Wachstum, Sanierungsbedarf und pädagogische Entwicklung endlich koordiniert statt punktuell lösen.',
    'Dohlenzelg/Chapf kann als leistungsfähiger Schwerpunktstandort gestärkt werden, sofern Kosten und Etappierung stimmen.',
    'Bessere Gruppen-, Förder- und Aufenthaltsräume können Unterrichtsqualität und Integration wirksam verbessern.',
    'Tagesstruktur kann familienfreundliche Standortqualität von Windisch stärken – aber nur mit politisch bewusst gewähltem Angebotsniveau.',
    'Gemeinde-/Schulbibliothek kann als gemeinsamer Bildungs- und Begegnungsort funktionieren, wenn Grösse und Betrieb realistisch sind.',
    'Phase 3 bietet Chance, Varianten transparent zu vergleichen und spätere Abstimmungen/Einwohnerratsentscheide besser abzustützen.'
]))

story.append(PageBreak())
story.append(P('6. Fragen für die Sitzung', 'H1N'))
story.append(P('A. Prognosen und Annahmen', 'H2N'))
story.extend(bullets([
    'Welche Annahmen zu Stadtraum Bahnhof sind politisch/vertraglich bereits gesichert – eigene Schule/KiGa, Zeitpunkt, Finanzierung?',
    'Wie aktuell sind Annahmen zu «Im Winkel» und weiteren Arealen? Gibt es ein jährliches Update der Schulraumprognose?',
    'Welche Sensitivität hat die Planung bei tieferer/höherer Geburtenrate – und wie wird Überdimensionierung vermieden?',
    'Welche Klassengrössen sind pädagogisch gewünscht und welche sind finanzpolitisch vertretbar?'
]))
story.append(P('B. Finanzen und Steuerbarkeit', 'H2N'))
story.extend(bullets([
    'Wann erhalten Einwohnerrat und Bevölkerung eine erste Grobkostenspanne pro Variante?',
    'Werden Betriebskosten, Personalfolgen, Reinigung, Unterhalt und Abschreibungen pro Variante ausgewiesen?',
    'Welche Massnahmen sind zwingend, welche optional, welche nur nice-to-have?',
    'Wie werden Provisorienkosten und Verzögerungsrisiken berücksichtigt?'
]))
story.append(P('C. Standort- und Angebotsstrategie', 'H2N'))
story.extend(bullets([
    'Welche Standorte sollen langfristig gestärkt werden – und gibt es Standorte, bei denen keine grösseren Investitionen mehr sinnvoll sind?',
    'Wie wird der Gebäudezustand in Phase 3 verbindlich einbezogen?',
    'Welches Zielniveau will die Gemeinde bei Tagesstrukturen: Grundversorgung, Ausbau, Tagesschule?',
    'Soll die Bibliothek am heutigen Standort bleiben, im Areal Dohlenzelg/Chapf neu organisiert oder anders gelöst werden?',
    'Wie werden Musikschule, Vereine, HPS, Aufgabenhilfe und Schulsozialarbeit integriert, ohne Exklusivflächen unnötig aufzublähen?'
]))
story.append(P('D. Oberstufe / Drittgemeinden', 'H2N'))
story.extend(bullets([
    'Ist eine zusätzliche Aufnahme von Lupfig/Birrhard politisch realistisch? Falls ja: mit welchem Kostenteiler?',
    'Wer trägt Investitions- und Betriebskosten für zusätzliche Oberstufenkapazitäten?',
    'Wie viele Reserveräume sind wirklich nötig und wie werden sie in normalen Jahren genutzt?'
]))

story.append(P('7. Empfohlene FDP-Position', 'H1N'))
story.append(P('<b>Grundhaltung:</b> Ja zur seriösen Phase 3, Nein zum Blankoscheck.', 'CalloutN'))
story.extend(bullets([
    'Phase 3 unterstützen, weil Handlungsbedarf plausibel und Nichtstun später teurer werden kann.',
    'Vor Variantenstudium klare politische Leitplanken verlangen: Standortstrategie, Tagesstruktur-Zielniveau, Bibliothek, Drittgemeinden, Gebäudezustand.',
    'Varianten müssen vergleichbar sein: Investitionskosten, Betriebskosten, Personalfolgen, Etappierung, Provisorien, Risiken.',
    'Priorisierung verlangen: zuerst Engpässe mit hoher Wirkung lösen (Dohlenzelg/Im Winkel, Gruppen-/Förderräume, Tagesstruktur-Entscheid), nicht flächendeckend Wunschstandard bauen.',
    'Modulare und etappierbare Lösungen bevorzugen, damit bei Prognoseabweichungen nachjustiert werden kann.',
]))

story.append(P('Formulierungsvorschlag', 'H2N'))
story.append(P('«Die FDP unterstützt eine solide Phase 3, weil der Handlungsbedarf nachvollziehbar ist. Entscheidend ist aber, dass wir jetzt nicht in eine Wunschplanung einsteigen, sondern in eine steuerbare Variantenplanung mit klaren Prioritäten, Grobkosten, Betriebskosten und Etappierung. Vor allem Tagesstruktur, Bibliothek, Standortstrategie, Drittgemeinden und Gebäudezustand müssen als politische Leitplanken geklärt werden.»', 'CalloutN'))

story.append(P('8. Quellen- und Prüfbemerkung', 'H1N'))
story.append(P('Geprüft gegen Bericht Phase 1+2, Raumverzeichnisse und OCR. Kernstellen: Prognosen S. 18–42, SOLL S. 66–71, Tagesstruktur/Bibliothek S. 70–74, Fazit S. 79, Pädagogik S. 80–81, Phase 3 S. 82–86. Finale Version verlangen.', 'SmallN'))


doc = SimpleDocTemplate(str(OUT), pagesize=A4, rightMargin=1.55*cm, leftMargin=1.55*cm, topMargin=1.55*cm, bottomMargin=1.4*cm, title='Sitzungsvorbereitung Schulraumplanung Windisch FDP')
doc.build(story, onFirstPage=footer, onLaterPages=footer)
print(OUT)
