#!/usr/bin/env python3
"""
Generator voor Werkinstructie_Voorjaarsconventie_2027_v1.0.docx
District 110AN - Voorjaarsconventie April 2027

OPERATIONELE werkinstructie: wat de conventiecommissie en de host club
CONCREET doen, stap voor stap, inclusief checklists.

Bronnen (alleen feiten uit Meta-Dossier):
- Handboek Lions Conventies vs 06 20240729 (logistiek, vlaggenceremonie, borrel, Lions-aankleding)
- Huishoudelijk Reglement MD 110 mei 2021 (registratie, stemkaarten/stembiljetten, termijnen)
- Werkplan AN 2026-2027 draft v1
- Districtbegroting 110 AN 25-26
- Club Health Assessment District 110AN (sept 2025)
- Conventie Roulatieschema
- Verslag Najaarsconventie 2024

Controleset (MOET consistent in alle deliverables):
District 110AN - Voorjaarsconventie April 2027 -
Stemrechten 1 per 10 leden (min 1, max 5) - Quorum >50% van stemgerechtigden.
"""

from docx import Document
from docx.shared import Cm, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import nsdecls
from docx.oxml import parse_xml
import os
from datetime import date

# == Constants & Factual Data (alleen uit Meta-Dossier) =====================
DISTRICT = "110AN"
CONVENTIE_TYPE = "Voorjaarsconventie (District Convention)"
CONVENTIE_MAAND = "April 2027"
GOVERNANCE = "Huishoudelijk Reglement MD 110 mei 2021"
STEMRECHT_REGEL = "1 stem per 10 leden per club (min 1, max 5)"
QUORUM_REGEL = ">50% van stemgerechtigden"
THEMA_2026_2027 = "Samen verder bouwen!"
VORIGE_ORGANISATOR = "LC Bussum Godelinde (FY 2025-2026)"
BUDGET_REF = "Districtbegroting 25-26: post '1 Districtsconventie' EUR 3.500"

# Logo: 754x676 px (ratio 1.115:1) -> geplaatst op 2.0cm x 1.8cm
# (python-docx zet Cm intern om naar EMU)
LOGO_PATHS = [
    "/root/projects/jg/2026-voorjaarsconventie-110an/assets/logo_jvg.png",
    "/root/projects/jg/2026-voorjaarsconventie-110an/assets/logo_jvg.jpg",
    "/root/projects/jg/2026-voorjaarsconventie-110an/assets/logo_jvg.jpeg",
]
LOGO_WIDTH_CM = 2.0
LOGO_HEIGHT_CM = 1.8

DOC_TITLE = "WERKINSTRUCTIE VOORJAARSCONVENTIE 2027"
DOC_VERSION = "Versie 1.0"
OUTPUT_PATH = "/root/projects/jg/2026-voorjaarsconventie-110an/working/Werkinstructie_Voorjaarsconventie_2027_v1.0.docx"

CHECKBOX = "\u2610"  # leeg checkbox-teken

CORP_BLUE = RGBColor(0x00, 0x33, 0x66)
CORP_MID = RGBColor(0x00, 0x66, 0x99)
CORP_TEXT = RGBColor(0x33, 0x33, 0x33)
CORP_GREY = RGBColor(0x66, 0x66, 0x66)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)


# == Helper functions =========================================================

def set_cell_shading(cell, color_hex: str):
    """Achtergrondkleur van een tabelcel instellen."""
    shading = parse_xml(f'<w:shd {nsdecls("w")} w:fill="{color_hex}"/>')
    cell._tc.get_or_add_tcPr().append(shading)


def add_heading_styled(doc, text: str, level: int):
    """Kop met corporate huisstijl (donkerblauw, Calibri)."""
    heading = doc.add_heading(text, level=level)
    for run in heading.runs:
        run.font.color.rgb = CORP_BLUE
        run.font.name = 'Calibri'
    return heading


def add_body_text(doc, text: str, bold=False, italic=False, size=Pt(11), alignment=None):
    """Body-paragraaf met huisstijl."""
    p = doc.add_paragraph()
    run = p.add_run(text)
    run.font.size = size
    run.font.name = 'Calibri'
    run.bold = bold
    run.italic = italic
    run.font.color.rgb = CORP_TEXT
    if alignment:
        p.alignment = alignment
    return p


def add_bullet(doc, text: str, level=0, bold_prefix=None):
    """Bullet met optioneel vet voorvoegsel."""
    p = doc.add_paragraph(style='List Bullet')
    p.paragraph_format.left_indent = Cm(1.27 + level * 1.27)
    if bold_prefix:
        run_b = p.add_run(bold_prefix)
        run_b.bold = True
        run_b.font.name = 'Calibri'
        run_b.font.size = Pt(11)
        run_b.font.color.rgb = CORP_TEXT
    run = p.add_run(text)
    run.font.name = 'Calibri'
    run.font.size = Pt(11)
    run.font.color.rgb = CORP_TEXT
    return p


def add_table_with_style(doc, data, col_widths=None, header_row=True):
    """Gestyleerde tabel: aanmaken, vullen, daarna stylen (kop donkerblauw/wit)."""
    rows = len(data)
    cols = len(data[0])
    table = doc.add_table(rows=rows, cols=cols, style='Table Grid')
    table.alignment = WD_TABLE_ALIGNMENT.CENTER
    if col_widths:
        for i, width in enumerate(col_widths):
            for row in table.rows:
                row.cells[i].width = Cm(width)
    # Vullen
    for r, row_data in enumerate(data):
        for c, cell_text in enumerate(row_data):
            table.rows[r].cells[c].text = str(cell_text)
    # Styling NA vullen (runs bestaan dan pas)
    if header_row:
        for cell in table.rows[0].cells:
            set_cell_shading(cell, "003366")
            for paragraph in cell.paragraphs:
                paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
                for run in paragraph.runs:
                    run.font.color.rgb = WHITE
                    run.font.bold = True
                    run.font.name = 'Calibri'
                    run.font.size = Pt(10)
    for row_idx, row in enumerate(table.rows):
        if header_row and row_idx == 0:
            continue
        for cell in row.cells:
            for paragraph in cell.paragraphs:
                for run in paragraph.runs:
                    run.font.name = 'Calibri'
                    run.font.size = Pt(10)
                    run.font.color.rgb = CORP_TEXT
    return table


def add_checklist_table(doc, items, col_widths=None):
    """Checklist-tabel: [checkbox] [Actie] [Wie] [Wanneer/Toelichting]."""
    data = [["\u2713", "Actie / Stap", "Wie", "Wanneer / Toelichting"]]
    for stap, wie, wann in items:
        data.append([CHECKBOX, stap, wie, wann])
    return add_table_with_style(doc, data, col_widths=col_widths or [1.0, 8.0, 3.5, 4.5])


def insert_logo(doc):
    """JvG-logo rechtsboven in de koptekst (754x676 px -> 2.0cm x 1.8cm)."""
    logo_path = next((p for p in LOGO_PATHS if os.path.exists(p)), None)
    if logo_path:
        section = doc.sections[0]
        header = section.header
        header.is_linked_to_previous = False
        p = header.paragraphs[0] if header.paragraphs else header.add_paragraph()
        p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
        run = p.add_run()
        run.add_picture(logo_path, width=Cm(LOGO_WIDTH_CM), height=Cm(LOGO_HEIGHT_CM))


def set_document_defaults(doc):
    """Standaard font en marges."""
    style = doc.styles['Normal']
    font = style.font
    font.name = 'Calibri'
    font.size = Pt(11)
    font.color.rgb = CORP_TEXT
    for section in doc.sections:
        section.top_margin = Cm(2.54)
        section.bottom_margin = Cm(2.54)
        section.left_margin = Cm(2.54)
        section.right_margin = Cm(2.54)


# == Document Generation ======================================================

def build_document():
    doc = Document()
    set_document_defaults(doc)
    insert_logo(doc)

    # -- TITELPAGINA -----------------------------------------------------------
    for _ in range(4):
        doc.add_paragraph()

    title = doc.add_paragraph()
    title.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = title.add_run(DOC_TITLE)
    run.font.size = Pt(28)
    run.font.bold = True
    run.font.color.rgb = CORP_BLUE
    run.font.name = 'Calibri'

    subtitle = doc.add_paragraph()
    subtitle.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = subtitle.add_run(f"District {DISTRICT}  \u2014  {CONVENTIE_MAAND}")
    run.font.size = Pt(16)
    run.font.color.rgb = CORP_MID
    run.font.name = 'Calibri'

    sub2 = doc.add_paragraph()
    sub2.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = sub2.add_run("Praktische uitvoeringshandleiding voor conventiecommissie en host club")
    run.font.size = Pt(12)
    run.font.italic = True
    run.font.color.rgb = CORP_GREY
    run.font.name = 'Calibri'

    doc.add_paragraph()
    version = doc.add_paragraph()
    version.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = version.add_run(DOC_VERSION)
    run.font.size = Pt(12)
    run.font.italic = True
    run.font.color.rgb = CORP_GREY
    run.font.name = 'Calibri'

    doc.add_paragraph()
    doc.add_paragraph()
    gov = doc.add_paragraph()
    gov.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = gov.add_run(f"Governance: {GOVERNANCE}")
    run.font.size = Pt(10)
    run.font.color.rgb = CORP_GREY
    run.font.name = 'Calibri'

    thema = doc.add_paragraph()
    thema.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = thema.add_run(f"Jaarthema 2026\u20132027: \"{THEMA_2026_2027}\"")
    run.font.size = Pt(11)
    run.font.italic = True
    run.font.color.rgb = CORP_MID
    run.font.name = 'Calibri'

    doc.add_page_break()

    # -- INHOUDSOPGAVE -----------------------------------------------------------
    add_heading_styled(doc, "Inhoudsopgave", level=1)
    for item in [
        "1. Doel",
        "2. Toepassingsgebied",
        "3. Benodigdheden",
        "4. Stapsgewijze uitvoering (checklists)",
        "5. Kwaliteitscontrole",
        "6. Probleemoplossing",
        "7. Verwante documenten",
        "Colofon",
    ]:
        add_body_text(doc, item, bold=True)
    doc.add_page_break()

    # == 1. DOEL ================================================================
    add_heading_styled(doc, "1. Doel", level=1)
    add_body_text(doc, (
        "Deze werkinstructie beschrijft OPERATIONEEL welke concrete taken de conventiecommissie en de "
        f"host club uitvoeren bij de organisatie van de {CONVENTIE_TYPE} van District {DISTRICT} in "
        f"{CONVENTIE_MAAND}. Waar de Procedure Voorjaarsconventie 2027 het WAT en WANNEER beschrijft, "
        "beschrijft deze werkinstructie het HOE: uitvoerbare stappen, checklists, benodigdheden en "
        "oplossingen voor veelvoorkomende problemen op de conventiedag zelf."
    ))
    add_body_text(doc, (
        "De instructie is bedoeld om direct op de werkvloer te gebruiken: afvinken tijdens de "
        "voorbereiding, als runbook op de conventiedag en als naslagwerk bij storingen."
    ))

    add_heading_styled(doc, "1.1 Kerndata (controleset)", level=2)
    kernset = [
        ["Gegeven", "Waarde", "Bron"],
        ["District", DISTRICT, "Club Health Assessment 110AN (sept 2025)"],
        ["Conventie", "Voorjaarsconventie " + CONVENTIE_MAAND, "Roulatieschema / Werkplan AN 2026-2027"],
        ["Locatie", "Volgens Conventie Roulatieschema (toerbeurt)", "Conventie Roulatieschema"],
        ["Stemrechten", STEMRECHT_REGEL, "HR / LCI Statuten art. 11"],
        ["Quorum", QUORUM_REGEL, "HR art. 15.4, 16"],
        ["Oproeping", "Min. 30 dagen vooraf aan alle clubs", "HR art. 2.1"],
        ["Registratie", "Vanaf min. 1 uur voor opening tot opening", "HR art. 3.1"],
        ["Aangifte stemgerechtigden", "Uiterlijk 24 uur voor aanvang, door clubbestuur", "HR art. 2.2"],
    ]
    add_table_with_style(doc, kernset, col_widths=[4.5, 8.0, 4.5])

    doc.add_page_break()

    # == 2. TOEPASSINGSGEBIED ===================================================
    add_heading_styled(doc, "2. Toepassingsgebied", level=1)

    add_heading_styled(doc, "2.1 Voor wie", level=2)
    add_bullet(doc, "Bestuur en actieve leden van de host club die de conventie logistiek verzorgen.")
    add_bullet(doc, "Leden van de conventiecommissie (organiserend comite) van het district.")
    add_bullet(doc, "Vrijwilligers bij registratie, zaaldienst, AV/techniek en ontvangst van gasten.")
    add_bullet(doc, "Het contactteam van de host club dat schakelt met de ambtelijk secretaris.")

    add_heading_styled(doc, "2.2 Wat valt eronder", level=2)
    add_bullet(doc, "Alle logistieke en praktische werkzaamheden: zaal, catering, AV, vlaggen en standaarden, "
                    "Lions-aankleding, registratiebalie, ondersteuning van het stembureau, diner en borrel.")
    add_bullet(doc, "De volledige voorbereidingsfase (van vaststelling locatie tot en met de generale "
                    "repetitie), de conventiedag(en) zelf en de nazorg/overdracht.")
    add_bullet(doc, "De afsluitende gezamenlijke borrel voor alle conventiegangers (vaste traditie van de "
                    "voorjaarsconventie, Handboek Lions Conventies).")

    add_heading_styled(doc, "2.3 Wat valt er NIET onder", level=2)
    add_bullet(doc, "Het vaststellen en versturen van de oproeping, agenda en conventiestukken "
                    "(ambtelijk secretaris; zie Procedure Voorjaarsconventie 2027, hoofdstuk 2 en 4).")
    add_bullet(doc, "Benoeming en instructie van het stembureau (gouverneursraad, HR art. 15).")
    add_bullet(doc, "De inhoudelijke besluitvorming, de telling en de vaststelling van stemuitslagen "
                    "(conventievoorzitter en stembureau).")
    add_bullet(doc, "Deze onderwerpen worden door de host club uitsluitend LOGISTIEK ondersteund: "
                    "materiaal, ruimte en personeel.")

    doc.add_page_break()

    # == 3. BENODIGDHEDEN =======================================================
    add_heading_styled(doc, "3. Benodigdheden", level=1)
    add_body_text(doc, (
        "De host club zorgt dat onderstaande zaken op locatie aanwezig en getest zijn, uiterlijk aan "
        "het einde van de opbouwdag (de dag voor de conventie)."
    ))

    add_heading_styled(doc, "3.1 Zaal en techniek", level=2)
    benodigd_zaal = [
        ["Categorie", "Benodigdheid", "Specificatie / Opmerking"],
        ["Zaal", "Plenaire zaal met podium of verhoging en spreekgestoelte", "Capaciteit conform verwachte opkomst (incl. partners/gasten)"],
        ["Zaal", "Aparte ruimte voor registratiebalie", "Bij entree, met tafels voor 2-3 balies"],
        ["Zaal", "Zaal voor (optioneel) vrijdagse diner en Get Together", "Handboek: vrijdag diner + Get Together borrel"],
        ["AV", "Microfoons (draadloos + vaste), geluidsinstallatie", "Testen tijdens generale repetitie"],
        ["AV", "Beamer/beeldscherm, laptops, presentatie-afstandsbediening", "Incl. reserve-laptop"],
        ["AV", "Muziekinstallatie voor volksliederen vlaggenceremonie", "USA / gastlanden / Wilhelmus couplet 1"],
        ["Decor", "Lions-aankleding: banners, standaarden, vlaggen", "Handboek: zorg voor voldoende Lions-aankleding, vlaggen en standaarden"],
        ["Decor", "Vlaggen: USA, vlaggen gastlanden, Nederlandse vlag + standaarden", "Volgorde: USA, buitenlandse gasten naar belangrijkheid, NL"],
        ["Meubilair", "Tafels en stoelen plenair, tafels stembureau en registratie", "Stembureau-tafel apart, zichtbaar"],
        ["Overig", "Naambordjes/badges, bordjes clubtafels, bordjes richtingaanwijzing", "Per balie en zaal"],
    ]
    add_table_with_style(doc, benodigd_zaal, col_widths=[2.5, 8.0, 6.5])

    add_heading_styled(doc, "3.2 Registratie en stemmateriaal (samen met ambtelijk secretaris)", level=2)
    benodigd_reg = [
        ["Benodigdheid", "Aantal / Specificatie", "Bron / Artikel HR"],
        ["Registratielijsten stemgerechtigden en niet-stemgerechtigden", "Geprint, per club gesorteerd + digitale versie", "HR art. 3.4"],
        ["Stemkaarten (stemmen over zaken)", "1 per stemgerechtigde; kleurgecodeerd indien gewenst", "HR art. 3.2, 16.1"],
        ["Stembiljetten (stemmen over personen)", "1 per geagendeerde stemming per stemgerechtigde", "HR art. 3.2, 17"],
        ["Gewaarmerkte herstemmingsbiljetten", "Voor eventuele herstemmingen; voorzien door gouverneursraad", "HR art. 3.3, 17.3"],
        ["Stembus/deugdelijke verzamelbakken", "1 per stemming", "HR art. 17"],
        ["Voorbeeld-stembiljet (groot, zaalbreed zichtbaar)", "Tonen vóór eerste schriftelijke stemming", "Praktijk / Handboek"],
        ["Latere schriftelijke adviezen", "Uitdelen bij registratie", "HR art. 5.2"],
    ]
    add_table_with_style(doc, benodigd_reg, col_widths=[6.5, 6.0, 4.5])

    add_heading_styled(doc, "3.3 Catering en hospitality", level=2)
    add_bullet(doc, "Koffie/thee bij aankomst en tijdens pauzes; lunch voor alle conventiegangers.")
    add_bullet(doc, "Vrijdagavond: diner en voorafgaand Get Together-borrel (gouverneurs, inkomende "
                    "gouverneurs, ambtelijk secretaris, ambtelijk penningmeester, internationale gasten "
                    "en partners) - Handboek Lions Conventies.")
    add_bullet(doc, "Internationale gasten worden uitgenodigd voor diner en conventie inclusief lunch en "
                    "borrel (Handboek).")
    add_bullet(doc, "Afsluitende gezamenlijke borrel voor alle conventiegangers na de sluiting.")
    add_bullet(doc, "Logistiek voor DG, VDG's, partners en gasten: diner en overnachting nabij de locatie "
                    "vooraf geregeld door host club.")

    doc.add_page_break()

    # == 4. STAPSGEWIJZE UITVOERING (CHECKLISTS) ================================
    add_heading_styled(doc, "4. Stapsgewijze uitvoering (checklists)", level=1)
    add_body_text(doc, (
        "Vink elke stap af na afronding. Bij twijfel of afwijking: raadpleeg hoofdstuk 6 "
        "(Probleemoplossing) en escalatie zoals beschreven in de Procedure (hoofdstuk 6)."
    ), italic=True)

    # 4.1 Voorbereiding
    add_heading_styled(doc, "4.1 Fase 1 - Voorbereiding logistiek (T-6 tot T-1 maand)", level=2)
    fase1 = [
        ("Vaststellen locatie, datum en capaciteit volgens Conventie Roulatieschema", "Commissie + DG", "T-6 mnd"),
        ("Contract met locatie tekenen (zaal, AV, catering, overnachtingstarieven)", "Host club penningmeester", "T-5 mnd"),
        ("Begroting opstellen conform " + BUDGET_REF + "; bewaking door host club", "Host club penningmeester", "T-5 mnd"),
        ("Werkgroepen vormen: zaal/techniek, registratie, hospitality, vlaggen/ceremonie", "Commissie", "T-4 mnd"),
        ("Definitieve zaalindeling tekenen (podium, stembureau, registratie, podiumopstelling)", "Werkgroep zaal/techniek", "T-3 mnd"),
        ("Vlaggen, standaarden en Lions-aankleding reserveren bij district/opvraag bij clubs", "Werkgroep vlaggen", "T-3 mnd"),
        ("Eten/drinken definitief bestellen incl. dieetwensen", "Werkgroep hospitality", "T-6 weken"),
        ("Diner vrijdag + overnachtingen gasten boeken (Handboek: gasten diner/lunch/borrel)", "Werkgroep hospitality", "T-6 weken"),
        ("Tijdschema conventiedag opstellen en afstemmen met ambtelijk secretaris", "Commissie", "T-1 mnd"),
        ("Vrijwilligersrooster maken (balie, zaaldienst, techniek, parkeerbegeleiding)", "Host club", "T-1 mnd"),
    ]
    add_checklist_table(doc, fase1)

    # 4.2 Opbouw
    add_heading_styled(doc, "4.2 Fase 2 - Opbouwdag (T-1 dag)", level=2)
    fase2 = [
        ("Zaal openen en opbouwen: podium, tafels, stoelen richting podium", "Werkgroep zaal/techniek", "Ochtend T-1"),
        ("AV opbouwen en VOLLEDIG testen: microfoons, beamer, muziek volksliederen", "Werkgroep techniek", "Middag T-1"),
        ("Vlaggen en standaarden plaatsen (volgorde: USA, gastlanden naar belangrijkheid, NL)", "Werkgroep vlaggen", "Middag T-1"),
        ("Lions-aankleding aanbrengen: banners, thema-bord jaarthema, Route 110AN-merchandise", "Werkgroep decor", "Middag T-1"),
        ("Registratiebalie inrichten: lijsten, badges, stemkaarten, stembiljetten, pennen", "Werkgroep registratie", "Middag T-1"),
        ("Stembureau-tafel inrichten met stembussen en voorbeeld-biljet", "Werkgroep + stembureau", "Middag T-1"),
        ("Generale repetitie: opening, vlaggenceremonie-muziek, microfooncheck sprekers", "Commissie + techniek", "Avond T-1"),
        ("Aankomst en ontvangst DG, VDG's, partners en internationale gasten", "Werkgroep hospitality", "Avond T-1"),
        ("Get Together borrel en diner vrijdagavond", "Werkgroep hospitality", "Avond T-1"),
        ("Laatste coördinatievergadering met conventievoorzitter (DG) en ambtelijk secretaris", "Commissie", "Avond T-1"),
    ]
    add_checklist_table(doc, fase2)

    # 4.3 Conventiedag
    add_heading_styled(doc, "4.3 Fase 3 - Conventiedag (runbook per tijdsmoment)", level=2)
    fase3 = [
        ("Openen gebouw, techniek aanzetten, laatste zaalcheck (T-3 uur)", "Werkgroep zaal/techniek", "T-3 uur"),
        ("Registratiebalie bezet vanaf TEN MINSTE 1 uur voor opening (HR art. 3.1)", "Registratiebureau", "T-1 uur tot opening"),
        ("Uitreiken stemkaart + stembiljet(en) aan ELKE stemgerechtigde bij registratie (HR art. 3.2)", "Registratiebureau", "Tijdens registratie"),
        ("Later ontvangen schriftelijke adviezen uitdelen aan bezoekers (HR art. 5.2)", "Registratiebureau", "Tijdens registratie"),
        ("Ontvangst en begeleiding internationale gasten en eregasten", "Werkgroep hospitality", "T-1 uur"),
        ("Na sluiting registratie: totaaltellingen direct naar voorzitter conventie (HR art. 3.5)", "Voorzitter registratiebureau", "Direct na sluiting"),
        ("Vlaggenceremonie uitvoeren: USA-vlag + fragment volkslied, gastlandvlaggen naar belangrijkheid, NL-vlag + geheel eerste couplet Wilhelmus", "Werkgroep vlaggen + techniek", "Aanvang programma"),
        ("Ondersteuning herdenking overleden Lions (kaars/tekst/ruimte; vast agenda-item)", "Werkgroep hospitality", "Programma"),
        ("Tijdens verkiezingen: stembiljeten uitdelen/verzamelen, stembussen beheren, ORDE bewaken", "Host club ondersteuning", "Bij elke stemming"),
        ("Zaaldienst: toesicht, deuren, geluid, temperatuur, halen/brengen sprekers", "Zaaldienst", "Hele dag"),
        ("Pauzes: koffie/thee/lunch op tijd, zaal op orde houden", "Werkgroep hospitality", "Programma"),
        ("Afsluitende gezamenlijke borrel voor alle conventiegangers", "Werkgroep hospitality", "Na sluiting"),
    ]
    add_checklist_table(doc, fase3)

    # 4.4 Nazorg
    add_heading_styled(doc, "4.4 Fase 4 - Nazorg en afbouw (T+1 tot T+2 weken)", level=2)
    fase4 = [
        ("Afbouwen zaal, terugbrengen vlaggen/standaarden/aankleding naar district", "Host club", "Dag zelf / T+1"),
        ("Rekeningen locatie en cateraar verzamelen en afhandelen", "Host club penningmeester", "T+1 week"),
        ("Financiële afrekening conform begroting (" + BUDGET_REF + ") overleggen aan district", "Host club penningmeester", "T+2 weken"),
        ("Terugkoppeling logistieke bevindingen aan evaluatiebijeenkomst commissie", "Host club contactpersoon", "T+2-3 weken"),
        ("Overdrachtmap logistiek (contacten, roosters, checklists) voor volgende roulatie", "Commissie + host club", "T+4 weken"),
    ]
    add_checklist_table(doc, fase4)

    doc.add_page_break()

    # == 5. KWALITEITSCONTROLE =================================================
    add_heading_styled(doc, "5. Kwaliteitscontrole", level=1)
    add_body_text(doc, (
        "Elke controle hieronder heeft een acceptatiecriterium. Alleen als aan het criterium is voldaan, "
        "wordt de bijbehorende checklist-stap in hoofdstuk 4 afgevinkt."
    ))

    add_heading_styled(doc, "5.1 Controles vóór en tijdens de conventie", level=2)
    qc = [
        ["Moment", "Controle", "Verantwoordelijke", "Acceptatiecriterium"],
        ["T-1 mnd", "Zaalindeling en tijdschema afgestemd met programma", "Commissie", "Schema akkoord DG + ambtelijk secretaris"],
        ["T-1 dag", "AV-test inclusief muziek volksliederen", "Werkgroep techniek", "Alle onderdelen zonder storing 1x volledig gedraaid"],
        ["T-1 dag", "Vlaggen compleet en in JUISTE volgorde", "Werkgroep vlaggen", "USA - gastlanden naar belangrijkheid - NL (Handboek)"],
        ["T-1 dag", "Stemmmateriaal geteld tegen registratielijst", "Registratie + stembureau", "Aantallen stemkaarten/biljetten = aantal verwachte stemgerechtigden"],
        ["T-1 uur", "Registratiebalie operationeel", "Registratiebureau", "Lijsten, badges, stemkaarten, biljetten, pennen klaar"],
        ["Opening", "Quorum vastgesteld op basis van registratie", "Voorzitter stembureau", QUORUM_REGEL + " - anders: zie 6.1"],
        ["Elke stemming", "Materiaal correct verdeeld en ingenomen", "Host club ondersteuning", "Stembureau kan storingvrij tellen"],
        ["Hele dag", "Tijdschema wordt gevolgd", "Commissie-voorzitter", "Max. 15 min afwijking per dagdeel"],
        ["Na sluiting", "Borrel en afronding verzorgd", "Werkgroep hospitality", "Alle conventiegangers bediend"],
    ]
    add_table_with_style(doc, qc, col_widths=[2.5, 6.0, 4.0, 4.5])

    add_heading_styled(doc, "5.2 Controles na de conventie", level=2)
    qc_post = [
        ["Moment", "Controle", "Verantwoordelijke", "Acceptatiecriterium"],
        ["T+1 week", "Zaalcatering en materiaal volledig retour", "Host club", "Geen openstaande leningen/retours"],
        ["T+2 weken", "Financiële afrekening compleet en binnen begroting", "Penningmeester host club", "Afwijkingen toegelicht aan DG"],
        ["T+3 weken", "Logistieke lessen gedocumenteerd", "Commissie + host club", "Input voor evaluatierapport opgeleverd"],
        ["T+4 weken", "Overdrachtmap compleet voor volgende roulatie", "Commissie", "Contacten, roosters, checklists gebundeld"],
    ]
    add_table_with_style(doc, qc_post, col_widths=[2.5, 6.0, 4.0, 4.5])

    doc.add_page_break()

    # == 6. PROBLEEMOPLOSSING ===================================================
    add_heading_styled(doc, "6. Probleemoplossing", level=1)
    add_body_text(doc, (
        "Veelvoorkomende problemen op de conventiedag en de direct toe te passen oplossing. "
        "Structurele afwijkingen worden vastgelegd en geëscaleerd conform de Procedure (hoofdstuk 6)."
    ))

    add_heading_styled(doc, "6.1 Probleem-actie-tabel", level=2)
    problemen = [
        ["Probleem", "Mogelijke oorzaak", "Directe actie (host club / commissie)", "Escalatie"],
        ["Quorum niet behaald bij opening",
         "Te weinig stemgerechtigden geregistreerd (" + QUORUM_REGEL + ")",
         "Registratie verlengen indien mogelijk; voorzitter laten aansporen; clubs ter plekke laten aanvullen aangifte (uiterlijk 24-uursregel controleren met secretaris)",
         "DG + voorzitter stembureau; HR art. 15.4, 18"],
        ["Ongeldige stemmen bij verkiezing",
         "Verkeerd biljet, meerdere namen aangekruist, toevoegingen (HR art. 17.4)",
         "Voorbeeld-biljet groot tonen vóór stemming; stembureau mondeling laten instrueren; gewaarmerkt herstemmingsbiljet inzetten",
         "Voorzitter stembureau"],
        ["AV-storing (microfoon/beamer/muziek)",
         "Defect of verkeerd aangesloten",
         "Reserve-laptop en reserve-microfoon inzetten; technicus standby (generalerepetitie-check); programma volgorde aanpassen",
         "Commissie-voorzitter"],
        ["Muziek volksliederen ontbreekt/stoort",
         "Bestanden niet aanwezig of verkeerde volgorde",
         "Backup-lijst (USB) op beide laptops; vaste volgorde: USA - gastlanden - Wilhelmus couplet 1",
         "Werkgroep techniek"],
        ["Vlag of standaard ontbreekt",
         "Niet geleverd door district/clubs",
         "Reserve-staanders en -vlaggen uit overdrachtmap; bij afwezigheid gast-vlag: ceremonie aanpassen i.o.m. DG",
         "DG"],
        ["Toeloop registratiebalie te groot",
         "Eén balie voor alle bezoekers",
         "Tweede balie openen (niet-stemgerechtigden apart); badges vooraf sorteren per club",
         "Registratiebureau"],
        ["Internationale gasten te laat/afwezig",
         "Vertraging of overmacht",
         "Programma flexibel houden; vlaggenceremonie-volgorde bijwerken; reserve-spreker/host regelen",
         "DG"],
        ["Catering te klein/groot",
         "Laatmutaties aanmeldingen",
         "Reservering buffer laten aanvullen door locatie; buffets aanvullen met drank/hapjes borrel",
         "Werkgroep hospitality"],
        ["Stemmateriaal onvolledig",
         "Tel- of bestelfout",
         "Direct laten aanvullen door gouverneursraad (herstemmingsbiljetten, HR art. 3.3); noodprint op locatie",
         "DG + stembureau"],
        ["Tijdsnood in programma",
         "Discussies/verkiezingen lopen uit",
         "Pauzes inkorten i.o.m. voorzitter; borrel-tijdstip communiceren; lunch verschuiven",
         "Commissie-voorzitter + DG"],
    ]
    add_table_with_style(doc, problemen, col_widths=[3.5, 3.5, 7.0, 3.0])

    add_heading_styled(doc, "6.2 Escalatielijn", level=2)
    escalatie = [
        ["Niveau", "Rol", "Wanneer"],
        ["1", "Werkgroepleider host club", "Alle logistieke problemen die het programma niet blokkeren"],
        ["2", "Voorzitter conventiecommissie", "Problemen die tijdschema of beleving raken"],
        ["3", "District Governor (conventievoorzitter)", "Direct op conventiedag: alles wat geldigheid, quorum of protocol raakt"],
        ["4", "Voorzitter stembureau", "Alles rond stemmingen, tellingen en stemuitslagen (HR art. 15-17)"],
    ]
    add_table_with_style(doc, escalatie, col_widths=[1.5, 7.0, 8.5])

    doc.add_page_break()

    # == 7. VERWANTE DOCUMENTEN =================================================
    add_heading_styled(doc, "7. Verwante documenten", level=1)
    verwant = [
        ["Document", "Relatie tot deze werkinstructie", "Status / Eigenaar"],
        ["Procedure Voorjaarsconventie 2027 v1.0", "Bovenliggend procesdocument: WAT en WANNEER (fases, RACI, kwaliteitscontroles)", "v1.0 - ter goedkeuring GR"],
        ["Huishoudelijk Reglement MD 110 (mei 2021)", "Formele basis: oproeping, registratie, stemrecht, stembureau, stemprocedures", "Vastgesteld mei 2021"],
        ["Handboek Lions Conventies (vs 06, 29-07-2024)", "Praktische conventie-ervaringen: logistiek, vlaggenceremonie, gasten, borrel", "Versie 06"],
        ["Conventie Roulatieschema", "Bepaalt welke club/district wanneer organiseert (toerbeurt)", "Districtsdocument"],
        ["Projectplan / PVA Voorjaarsconventie 2027 v1.0", "Planning, middelen en risico's van het project", "v1.0 - projectteam"],
        ["Werkplan AN 2026-2027", "Jaarprogramma, thema \"" + THEMA_2026_2027 + "\", verkiezingen 1e/2e VDG en DG", "Draft v1"],
        ["Districtbegroting 110 AN 25-26", "Financiële referentie: post '1 Districtsconventie' EUR 3.500", "Vastgesteld"],
        ["Club Health Assessment 110AN (sept 2025)", "Ledenaantallen per club voor indicatieve stemrechtberekening (1/10, min 1/max 5)", "Sept 2025"],
        ["Verslag Najaarsconventie 17-10-2024", "Lessen uit vorige conventie (registratie, verloop, gasten)", "Definitief"],
    ]
    add_table_with_style(doc, verwant, col_widths=[5.5, 8.0, 3.5])

    # -- COLOFON ---------------------------------------------------------------
    doc.add_paragraph()
    add_heading_styled(doc, "Colofon", level=1)
    colofon = [
        f"Document: Werkinstructie Voorjaarsconventie 2027 v1.0",
        f"District: {DISTRICT}",
        f"Conventie: Voorjaarsconventie {CONVENTIE_MAAND}",
        f"Datum aanmaak: {date.today().isoformat()}",
        f"Governance basis: {GOVERNANCE}",
        "Auteur: Conventiecommissie 2026-2027 i.s.m. host club en ambtelijk secretaris",
        "Versiebeheer: v1.0 - initiële versie, aansluitend op Procedure Voorjaarsconventie 2027 v1.0",
        "Volgende review: na evaluatie voorjaarsconventie 2027 (vóór roulatie-overdracht)",
        "Controleset: District " + DISTRICT + " · April 2027 · stemrechten 1/10 (min 1, max 5) · quorum >50%",
    ]
    for item in colofon:
        add_bullet(doc, item)

    return doc


def main():
    doc = build_document()
    doc.save(OUTPUT_PATH)
    print(f"Document gegenereerd: {OUTPUT_PATH}")


if __name__ == "__main__":
    main()
