#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Genereert 05_Checklist_Ledenontmoetingsavond.xlsx
Lions Clubs International - District 110 AN
Ledenontmoetingsavond 13 oktober 2026 (+ 2e VDG aankondiging)
Bron: working/meta-dossier_v1.md + research/sources.md (33 bronnen, Tier 1/2/3)
"""
import os
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter
from openpyxl.worksheet.datavalidation import DataValidation

OUT = "/root/projects/jg/2026-pbm-ledenontmoetingsavond-13okt/deliverables/docx/05_Checklist_Ledenontmoetingsavond.xlsx"

NAVY, PHASE, GREY = "1F3864", "2E5496", "F2F2F2"
thin = Side(style="thin", color="B0B0B0")
border = Border(left=thin, right=thin, top=thin, bottom=thin)

HDR_FONT = Font(name="Calibri", size=11, bold=True, color="FFFFFF")
SEC_FONT = Font(name="Calibri", size=11, bold=True, color="FFFFFF")
TITLE_FONT = Font(name="Calibri", size=14, bold=True, color=NAVY)
SUB_FONT = Font(name="Calibri", size=10, italic=True, color="555555")
BODY_FONT = Font(name="Calibri", size=10)

HDR_FILL = PatternFill("solid", fgColor=NAVY)
SEC_FILL = PatternFill("solid", fgColor=PHASE)
ALT_FILL = PatternFill("solid", fgColor=GREY)

WRAP = Alignment(wrap_text=True, vertical="top")
WRAPC = Alignment(wrap_text=True, vertical="center", horizontal="center")

HEADERS = ["Omschrijving", "Verantwoordelijke (rol)", "Status", "Datum voltooid (dd-mm-jjjj)", "Opmerkingen"]
WIDTHS = [72, 26, 14, 22, 46]

R = {
    "PL": "Projectleider evenement",
    "DG": "District Governor",
    "VDG1": "1e Vice District Governor",
    "KAB": "Kabinet / bestuur",
    "COM": "Co\u00f6rd. communicatie",
    "LOC": "Co\u00f6rd. locatie & techniek",
    "REG": "Co\u00f6rd. registratie",
    "CAT": "Co\u00f6rd. catering",
    "VEI": "Verantw. veiligheid",
    "NOT": "Notulist",
    "GMT": "GMT-voorzitter",
    "FIN": "Penningmeester district",
    "SEC": "District Secretaris",
}

wb = Workbook()
wb.remove(wb.active)

def add_sheet(title, subtitle, sections):
    ws = wb.create_sheet(title)
    ncol = len(HEADERS)
    ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=ncol)
    c = ws.cell(row=1, column=1, value="Lions District 110 AN \u2014 Ledenontmoetingsavond 13 oktober 2026")
    c.font = TITLE_FONT
    ws.merge_cells(start_row=2, start_column=1, end_row=2, end_column=ncol)
    c = ws.cell(row=2, column=1, value=subtitle)
    c.font = SUB_FONT
    row = 4
    for i, h in enumerate(HEADERS, 1):
        c = ws.cell(row=row, column=i, value=h)
        c.font = HDR_FONT; c.fill = HDR_FILL; c.border = border; c.alignment = WRAPC
    ws.row_dimensions[row].height = 24
    header_row = row
    row += 1
    for sec_name, items in sections:
        ws.merge_cells(start_row=row, start_column=1, end_row=row, end_column=ncol)
        c = ws.cell(row=row, column=1, value=sec_name)
        c.font = SEC_FONT; c.fill = SEC_FILL; c.alignment = WRAP
        ws.row_dimensions[row].height = 18
        row += 1
        for j, (item, resp) in enumerate(items):
            vals = [item, resp, "\u2610 Open", "", ""]
            for i, v in enumerate(vals, 1):
                c = ws.cell(row=row, column=i, value=v)
                c.font = BODY_FONT; c.border = border
                c.alignment = WRAP if i in (1, 2, 5) else WRAPC
                if j % 2 == 1:
                    c.fill = ALT_FILL
            row += 1
        row += 1
    for i, w in enumerate(WIDTHS, 1):
        ws.column_dimensions[get_column_letter(i)].width = w
    dv = DataValidation(type="list",
        formula1='"\u2610 Open,\u25d0 Bezig,\u2714 Afgerond,\u2718 Geannuleerd,\u2796 N.v.t."',
        allow_blank=True)
    ws.add_data_validation(dv)
    dv.add("C{}:C{}".format(header_row + 1, row))
    ws.freeze_panes = "A{}".format(header_row + 1)
    ws.auto_filter.ref = "A{}:{}{}".format(header_row, get_column_letter(ncol), row)
    return ws

# ============ TABBLAD 1 - VOORBEREIDING (T-12 tot T-8) ============
tab1 = [
    ("1.1 Kick-off meeting", [
        ("Kick-off meeting inplannen en agendapunten opstellen (doel, scope, planning, rollen)", R["PL"]),
        ("Belanghebbenden uitnodigen: DG, 1e VDG, kabinetsleden, GMT-voorzitter, zonevoorzitters", R["PL"]),
        ("Opdrachtformulering en doelstellingen vastleggen: ledenontmoeting + aankondiging 2e VDG", R["DG"]),
        ("Projectteam en verantwoordelijkheden (RACI) bevestigen en vastleggen", R["PL"]),
        ("Budgetkader vaststellen conform Districtbegroting (locatie, catering, communicatie)", R["FIN"]),
        ("Risico-inventarisatie doornemen (locatie, 2e VDG-kandidaat, opkomst, budget, compliance)", R["PL"]),
        ("Governance-toetsing inplannen: MD110 Statuten, HR MD110, Protocol MD-Organen, LCI-regelgeving", R["KAB"]),
        ("Kick-off notulen maken en verspreiden naar alle deelnemers", R["NOT"]),
        ("Projectplan (concept) opstellen conform MASTER_SOP \u00a73.5", R["PL"]),
    ]),
    ("1.2 Locatie boeking", [
        ("Wensenlijst locatie opstellen (capaciteit conform verwacht deelnemersaantal, bereikbaarheid, parkeren, AV)", R["LOC"]),
        ("Locaties inventariseren op centraal punt in district 110 AN", R["LOC"]),
        ("Offertes opvragen (zaal, catering, techniek, borg)", R["LOC"]),
        ("Locatiebezoek doen en geschiktheid beoordelen (toegankelijkheid, akoestiek, veiligheid)", R["LOC"]),
        ("Locatie boeken en bevestiging schriftelijk vastleggen (contract/reservering)", R["PL"]),
        ("Annuleringsvoorwaarden en betalingstermijnen documenteren", R["FIN"]),
        ("Bereikbaarheid en parkeergelegenheid vastleggen voor communicatie naar deelnemers", R["COM"]),
        ("Alternatieve locatie (plan B) vaststellen - mitigatie risico 'locatie niet beschikbaar'", R["LOC"]),
    ]),
    ("1.3 Team samenstelling", [
        ("Projectleider evenement benoemen (aansturing namens DG/kabinet)", R["DG"]),
        ("Co\u00f6rdinator locatie & techniek aanwijzen", R["PL"]),
        ("Co\u00f6rdinator registratie & ontvangst aanwijzen", R["PL"]),
        ("Co\u00f6rdinator catering aanwijzen", R["PL"]),
        ("Co\u00f6rdinator communicatie & uitnodigingen aanwijzen", R["COM"]),
        ("Verantwoordelijke veiligheid & noodprocedures aanwijzen", R["VEI"]),
        ("Notulist/verslaglegger voor de avond aanwijzen", R["NOT"]),
        ("Vervangers/back-up vastleggen per rol (wie vervangt wie bij afwezigheid)", R["PL"]),
        ("Taakverdeling committeren conform kabinetsstructuur en Taakverdeling GR", R["KAB"]),
    ]),
]
add_sheet("1 Voorbereiding", "Fase 1: Voorbereiding \u2014 T-12 tot T-8 weken (ca. 14 juli t/m medio augustus 2026)", tab1)

# ============ TABBLAD 2 - PLANNING (T-8 tot T-2) ============
tab2 = [
    ("2.1 Uitnodigingen", [
        ("Deelnemerslijst samenstellen (alle clubs en leden district 110 AN; bron: ledenoverzicht)", R["COM"]),
        ("Adresbestand verifi\u00ebren en actualiseren (e-mail/post)", R["REG"]),
        ("Uitnodiging opstellen in huisstijl 110 AN (template briefpapier)", R["COM"]),
        ("Aanmelddeadline opnemen in uitnodiging (uiterlijk T-1 week)", R["COM"]),
        ("Uitnodiging ter goedkeuring voorleggen aan DG en communicatieco\u00f6rdinator", R["DG"]),
        ("Save-the-date versturen (T-8 weken)", R["COM"]),
        ("Definitieve uitnodiging versturen naar alle clubs/leden (T-6 weken)", R["COM"]),
        ("Herinnering versturen inclusief definitief programma (T-2 weken)", R["COM"]),
        ("Aanmeldingen registreren en deelnemersaantal monitoren", R["REG"]),
        ("Bij lage aanmelding: persoonlijke oproep via zonevoorzitters (mitigatie risico 'lage opkomst')", R["GMT"]),
    ]),
    ("2.2 Programma", [
        ("Programmaontwerp opstellen (ontvangst, opening DG, ledenontmoeting, aankondiging 2e VDG, afsluiting/borrel)", R["PL"]),
        ("Sprekers en sessieleiders bevestigen (DG, 1e VDG, GMT-voorzitter, evt. gastspreker)", R["PL"]),
        ("Programmaonderdeel 'aankondiging 2e VDG' vormgeven (moment, spreker, protocol)", R["DG"]),
        ("Tijdschema opstellen met marges en pauzes", R["PL"]),
        ("Interactieve ledenontmoeting-invulling ontwerpen (zone-tafels/speed-meet; ref. Inspiratie avond 110AN)", R["GMT"]),
        ("Programma afstemmen met locatie (zaalbezetting, doorlooptijden)", R["LOC"]),
        ("Definitief programma vaststellen en laten goedkeuren door DG", R["DG"]),
        ("Programma verwerken in uitnodiging, herinnering en presentatie", R["COM"]),
    ]),
    ("2.3 Communicatie", [
        ("Communicatieplan opstellen (e-mail, districtwebsite, clubnieuwsbrieven, social media)", R["COM"]),
        ("Berichtenkalender opstellen (T-8 save-the-date, T-6 uitnodiging, T-2 herinnering, T-3d laatste info)", R["COM"]),
        ("Drukmateriaal bestellen (borden, programmaboekjes, naambadges)", R["COM"]),
        ("Persbericht opstellen voor lokale media (optioneel, in afstemming met DG)", R["COM"]),
        ("Districtwebsite/-kalender bijwerken met evenementdetails", R["COM"]),
        ("Laatste informatiebrief versturen (T-3 dagen): route, parkeren, programma, aanvangstijd", R["COM"]),
    ]),
    ("2.4 2e VDG benoeming (voorbereiding)", [
        ("Benoemingsprocedure verifi\u00ebren conform MD110 Statuten \u00a74.2", R["KAB"]),
        ("Kandidaatselectieproces afronden in overleg DG en nominatiecommissie", R["DG"]),
        ("Bereidheid kandidaat bevestigen v\u00f3\u00f3r openbare aankondiging (informed consent)", R["DG"]),
        ("Aankondigingstekst opstellen en toetsen aan MD110 Statuten en Huishoudelijk Reglement", R["KAB"]),
        ("Benoemingsmoment integreren in programma en toespraak DG", R["DG"]),
        ("Informatie over 2e VDG-training en ledenaantal-doelstellingen paraat hebben", R["VDG1"]),
        ("Plan B vaststellen indien kandidaat niet tijdig beschikbaar (risico '2e VDG niet tijdig benoemd')", R["DG"]),
    ]),
]
add_sheet("2 Planning", "Fase 2: Planning \u2014 T-8 tot T-2 weken (medio augustus t/m eind september 2026)", tab2)

# ============ TABBLAD 3 - UITVOERING (T0 - 13 oktober 2026) ============
tab3 = [
    ("3.1 Opbouw", [
        ("Opbouwploeg vaststellen; aanwezig 3-4 uur voor aanvang", R["LOC"]),
        ("Zaalopbouw volgens plattegrond (tafels per zone, podium, registratiebalie)", R["LOC"]),
        ("Geluid, microfoons en beamer installeren en testen", R["LOC"]),
        ("Presentatie laden + back-up op USB en in cloud", R["LOC"]),
        ("Signage plaatsen (routewijzing, zaal, sanitair, nooduitgangen)", R["LOC"]),
        ("Decor, borden en programmamateriaal plaatsen", R["LOC"]),
        ("Registratiebalie inrichten (aanmeldlijst, badges, walk-in formulieren)", R["REG"]),
        ("Eindcontrole zaal door projectleider", R["PL"]),
    ]),
    ("3.2 Registratie", [
        ("Aanmeldlijst en walk-in registratieformulieren klaarleggen", R["REG"]),
        ("Naambadges alfabetisch sorteren en uitdelen", R["REG"]),
        ("Aanwezigheidsregistratie laten tekenen (bestuurlijk/archief)", R["REG"]),
        ("Aantal aanwezigen tellen en rapporteren aan caterer en projectleider", R["REG"]),
        ("Laatkomers ontvangen en plaatsen zonder storing van programma", R["REG"]),
        ("Contactpersoon EHBO/noodteam bekend maken bij registratie", R["VEI"]),
    ]),
    ("3.3 Presentatie", [
        ("Presentatie finaal checken (volgorde, video's, microfoonvolume)", R["LOC"]),
        ("Opening en welkomstwoord DG volgens protocol", R["DG"]),
        ("Programmaleider/regisseur voor de avond aanwijzen (tijdswaking)", R["PL"]),
        ("Moment aankondiging 2e VDG uitvoeren conform script en protocol", R["DG"]),
        ("Ledenontmoeting-sessies begeleiden (timeboxes, microfoon doorgeven)", R["GMT"]),
        ("Vragenronde/interactie faciliteren", R["PL"]),
        ("Afsluiting en dankwoord DG/kabinet", R["DG"]),
        ("Presentatie en sprekersnotities veiligstellen voor verslag", R["NOT"]),
    ]),
    ("3.4 Catering", [
        ("Definitieve aantallen bevestigen bij caterer (T-3 dagen en op de dag zelf)", R["CAT"]),
        ("Dieetwensen verzameld en doorgegeven (vegetarisch, allergie\u00ebn)", R["CAT"]),
        ("Ontvangst koffie/thee gereed v\u00f3\u00f3r opening", R["CAT"]),
        ("Pauze/borrel op het juiste moment laten serveren (afstemming programma)", R["CAT"]),
        ("Bijvullen monitoren gedurende de avond", R["CAT"]),
        ("Afrekening controleren en factuurgegevens vastleggen", R["FIN"]),
        ("Afval en terugloop afstemmen met locatie", R["CAT"]),
    ]),
    ("3.5 Veiligheid", [
        ("Nooduitgangen controleren: vrij en ontgrendeld", R["VEI"]),
        ("EHBO-set en AED-locatie verifi\u00ebren; locatiepersoneel informeren", R["VEI"]),
        ("Evacuatieplan van locatie opvragen en team instrueren", R["VEI"]),
        ("Maximale zaalbezetting controleren", R["VEI"]),
        ("Struikel-/valgevaar inspecteren (kabels, verlichting, vloerbedekking)", R["VEI"]),
        ("Contactgegevens locatiebeheerder en noodnummers opnemen in teaminstructie", R["VEI"]),
    ]),
    ("3.6 Noodprocedures", [
        ("Noodteam samenstellen en rollen toewijzen (co\u00f6rdinatie, evacuatie, medisch, communicatie)", R["VEI"]),
        ("Noodnummerlijst opstellen (112, locatiebeheerder, DG, projectleider)", R["VEI"]),
        ("Scenario-afspraken: brand/evacuatie, medisch incident, stroom/AV-storing", R["VEI"]),
        ("Back-upplan bij AV-storing (reserve geluid, geprinte presentatie)", R["LOC"]),
        ("Alternatief programma-/sprekerschema bij vertraging vaststellen", R["PL"]),
        ("Instructiekaarten noodteam klaarleggen op registratiebalie", R["REG"]),
        ("Na afloop: incidenten registreren en melden (verzekering/archief)", R["NOT"]),
    ]),
]
add_sheet("3 Uitvoering", "Fase 3: Uitvoering \u2014 T0: dinsdag 13 oktober 2026 (evenementdag)", tab3)

# ============ TABBLAD 4 - NAZORG (T+1 dag tot T+1 week) ============
tab4 = [
    ("4.1 Verslaglegging", [
        ("Verslag van de avond opstellen (aanwezigen, programma, aankondiging 2e VDG, besluiten/punten)", R["NOT"]),
        ("Foto's/video's verzamelen en selecteren (toestemming publicatie checken)", R["COM"]),
        ("Aanwezigheidslijst digitaliseren en archiveren", R["REG"]),
        ("Financieel overzicht maken (uitgaven t.o.v. budget)", R["FIN"]),
        ("Presentatie en materialen archiveren in projectmap", R["PL"]),
        ("Verslag verspreiden naar DG, kabinet en clubbesturen", R["SEC"]),
    ]),
    ("4.2 Evaluatie", [
        ("Digitaal evaluatieformulier versturen naar deelnemers (uiterlijk T+2 dagen)", R["COM"]),
        ("Debriefmeeting plannen met projectteam (T+1 week)", R["PL"]),
        ("Opkomst- en tevredenheidsdata analyseren", R["PL"]),
        ("Lessen-learned document opstellen (wat ging goed / verbeterpunten)", R["NOT"]),
        ("Budget-eindafrekening controleren en goedkeuren (begroting vs. werkelijk)", R["FIN"]),
        ("Evaluatierapport opstellen en indienen bij DG/kabinet", R["PL"]),
    ]),
    ("4.3 Follow-up", [
        ("Nieuw benoemde 2e VDG feliciteren en introduceren in districtcommunicatie", R["DG"]),
        ("2e VDG opnemen in kabinetstructuur en opvolging in orde brengen (Protocol MD-Organen)", R["KAB"]),
        ("Aanmeldingen interesse clubactiviteiten/GMT doorzetten naar betreffende teams", R["GMT"]),
        ("Openstaande actiepunten uit verslag toewijzen met deadline", R["PL"]),
        ("Bedankje versturen aan locatie, caterer, sprekers en vrijwilligers", R["COM"]),
        ("Datum volgend districtsevenement agenderen in districtkalender", R["SEC"]),
        ("Projectmap afsluiten en overdragen conform districtarchief", R["SEC"]),
    ]),
]
add_sheet("4 Nazorg", "Fase 4: Nazorg \u2014 T+1 dag tot T+1 week (14 t/m 20 oktober 2026)", tab4)

# ============ TABBLAD 5 - GOVERNANCE COMPLIANCE ============
tab5 = [
    ("5.1 LCI compliance (International Constitution, Board Policy Manual)", [
        ("Toets evenementsopzet aan LCI International Constitution and By-Laws (districtstructuur)", R["KAB"]),
        ("Vaststellen: geen strijdigheid met Board Policy Manual-richtlijnen voor district events", R["KAB"]),
        ("Ethische standaarden DG (Ethical Standards and Conduct) gerespecteerd in programma en communicatie", R["DG"]),
        ("Reis-/onkostenvergoedingen conform LCI/MD110-regelgeving per 01-07-2023 verwerken", R["FIN"]),
        ("District Election Guidelines geraadpleegd indien aankondiging raakt aan verkiezingsproces", R["KAB"]),
        ("Use of LCI-merk/huisstijl conform brand guidelines", R["COM"]),
        ("Verzekeringen/aansprakelijkheid evenement gecheckt (LCI en locatie)", R["PL"]),
    ]),
    ("5.2 MD110 Statuten & Huishoudelijk Reglement", [
        ("Aankondigingsprocedure 2e VDG conform MD110 Statuten \u00a74.2 uitgevoerd/gevalideerd", R["KAB"]),
        ("District bijeenkomst georganiseerd conform HR MD110 artikel 12 (protocol district bijeenkomsten)", R["PL"]),
        ("Actuele HR-versie gehanteerd (mei 2021 / concept 2025) \u2014 versie vastgelegd in projectmap", R["SEC"]),
        ("Besluitvorming en communicatieprocessen conform HR MD110 doorlopen", R["SEC"]),
        ("Geschillenprocedure (District Dispute Resolution Procedure) paraat bij bezwaren", R["KAB"]),
        ("Notulen en besluiten conform statutaire verslagleggingseisen vastgelegd", R["SEC"]),
    ]),
    ("5.3 Protocol MD-Organen V1.0", [
        ("Rol van het kabinet bij het evenement conform Protocol MD-Organen \u00a73.1 ingevuld", R["KAB"]),
        ("Samenstelling en taakverdeling van betrokken MD-organen gedocumenteerd", R["SEC"]),
        ("Overdrachtsprocedures: evenementsdocumentatie overdraagbaar gemaakt voor opvolgend bestuur", R["SEC"]),
        ("Verslaglegging conform protocolvereisten MD-Organen (vastlegging, goedkeuring, archief)", R["SEC"]),
        (" Compliance-matrix uit meta-dossier tabblad nagelopen en ondertekend", R["PL"]),
        ("Openstaande compliance-punten gerapporteerd aan DG met herstelacties", R["PL"]),
    ]),
]
add_sheet("5 Governance Compliance", "Governance \u2014 LCI / MD110 Statuten & HR / Protocol MD-Organen (doorlopend, afronding T+1 week)", tab5)

# ============ OPSLAAN ============
os.makedirs(os.path.dirname(OUT), exist_ok=True)
wb.save(OUT)

# Kort verslag
from openpyxl import load_workbook
chk = load_workbook(OUT)
total = 0
for s in chk.sheetnames:
    ws = chk[s]
    n = sum(1 for row in ws.iter_rows(min_col=3) if isinstance(row[0].value, str) and "Open" in row[0].value)
    total += n
    print("{}: {} items".format(s, n))
print("TOTAAL items: {}".format(total))
print("Opgeslagen:", OUT, "-", os.path.getsize(OUT), "bytes")
