#!/usr/bin/env python3
"""
PGS-15 Compliance Kennisdossier — Phoenix Metals IJmuiden
Document 1/12 — Kennisdossier (.docx)
Versie: 1.0 | Datum: 2026-04-26
Styleguide: MASTER_STYLEGUIDE v1.2 compliant
"""

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

# === CONFIG ===
OUTPUT = "/root/projects/jg/2026-pgs15-phoenix-metals/deliverables/docx/PGS15_Kennisdossier_PhoenixMetals_v1.0.docx"
LOGO = "/root/projects/jg/2026-pgs15-phoenix-metals/assets/branding/jvg-consultancy-logo.jpg"
PRIMARY = RGBColor(0x00, 0x33, 0x66)  # #003366
TEXT_DARK = RGBColor(0x1F, 0x29, 0x37)
TEXT_SEC = RGBColor(0x37, 0x41, 0x51)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
SUCCESS = RGBColor(0x00, 0xA8, 0x59)
WARNING = RGBColor(0xF5, 0x9E, 0x0B)
CRITICAL = RGBColor(0xFF, 0x6D, 0x00)
ERROR_C = RGBColor(0xEF, 0x44, 0x44)

doc = Document()

# === STYLES ===
style = doc.styles['Normal']
font = style.font
font.name = 'Calibri'
font.size = Pt(11)
font.color.rgb = TEXT_DARK

for level in range(1, 4):
    h = doc.styles[f'Heading {level}']
    h.font.name = 'Calibri'
    h.font.color.rgb = PRIMARY
    h.font.bold = True
    if level == 1:
        h.font.size = Pt(24)
    elif level == 2:
        h.font.size = Pt(18)
    else:
        h.font.size = Pt(14)

# Helper functions
def add_table(headers, rows, col_widths=None):
    table = doc.add_table(rows=1 + len(rows), cols=len(headers))
    table.style = 'Table Grid'
    table.alignment = WD_TABLE_ALIGNMENT.CENTER
    # Header row
    for i, h in enumerate(headers):
        cell = table.rows[0].cells[i]
        cell.text = ''
        p = cell.paragraphs[0]
        run = p.add_run(h)
        run.bold = True
        run.font.color.rgb = WHITE
        run.font.size = Pt(10)
        run.font.name = 'Calibri'
        p.alignment = WD_ALIGN_PARAGRAPH.CENTER
        shading = parse_xml(f'<w:shd {nsdecls("w")} w:fill="003366"/>')
        cell._tc.get_or_add_tcPr().append(shading)
    # Data rows
    for r_idx, row in enumerate(rows):
        for c_idx, val in enumerate(row):
            cell = table.rows[r_idx + 1].cells[c_idx]
            cell.text = ''
            p = cell.paragraphs[0]
            run = p.add_run(str(val))
            run.font.size = Pt(10)
            run.font.name = 'Calibri'
            # Alternating rows
            if r_idx % 2 == 1:
                shading = parse_xml(f'<w:shd {nsdecls("w")} w:fill="F8F9FA"/>')
                cell._tc.get_or_add_tcPr().append(shading)
    if col_widths:
        for i, w in enumerate(col_widths):
            for row in table.rows:
                row.cells[i].width = Cm(w)
    doc.add_paragraph()
    return table

def add_para(text, bold=False, size=11, align=None, color=None):
    p = doc.add_paragraph()
    run = p.add_run(text)
    run.bold = bold
    run.font.size = Pt(size)
    run.font.name = 'Calibri'
    if color:
        run.font.color.rgb = color
    if align:
        p.alignment = align
    return p

def add_bullet(text, level=0):
    p = doc.add_paragraph(text, style='List Bullet')
    p.paragraph_format.left_indent = Cm(1.5 + level * 1.0)
    return p

# =============================================
# VOORBLAD
# =============================================
doc.add_paragraph()
doc.add_paragraph()
if os.path.exists(LOGO):
    doc.add_picture(LOGO, width=Inches(2.5))
    doc.paragraphs[-1].alignment = WD_ALIGN_PARAGRAPH.CENTER

doc.add_paragraph()
add_para("PGS-15 COMPLIANCE", bold=True, size=28, align=WD_ALIGN_PARAGRAPH.CENTER, color=PRIMARY)
add_para("KENNISDOSSIER", bold=True, size=28, align=WD_ALIGN_PARAGRAPH.CENTER, color=PRIMARY)
doc.add_paragraph()
add_para("Phoenix Metals IJmuiden", bold=True, size=18, align=WD_ALIGN_PARAGRAPH.CENTER, color=TEXT_SEC)
add_para("Opslag van Verpakte Gevaarlijke Stoffen", size=14, align=WD_ALIGN_PARAGRAPH.CENTER, color=TEXT_SEC)
doc.add_paragraph()

# Meta table
meta_data = [
    ("Project", "2026-pgs15-phoenix-metals"),
    ("Opdrachtgever", "Phoenix Metals IJmuiden"),
    ("Adviseur", "JvG Consultancy — HSEQ Divisie"),
    ("Versie", "1.0"),
    ("Datum", "26 april 2026"),
    ("Classificatie", "Vertrouwelijk"),
    ("Bron", "PGS 15:2025 versie 1.0 (januari 2025)"),
    ("Status", "Definitief"),
]
for label, value in meta_data:
    p = doc.add_paragraph()
    p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run_l = p.add_run(f"{label}: ")
    run_l.bold = True
    run_l.font.size = Pt(11)
    run_l.font.name = 'Calibri'
    run_v = p.add_run(value)
    run_v.font.size = Pt(11)
    run_v.font.name = 'Calibri'

doc.add_paragraph()
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run("⚠️ VERTROUWELIJK")
run.bold = True
run.font.size = Pt(12)
run.font.color.rgb = CRITICAL
doc.add_paragraph()
add_para("Dit document is vertrouwelijk en uitsluitend bestemd voor Phoenix Metals IJmuiden en JvG Consultancy. Ongeautoriseerde verspreiding is verboden.", size=10, align=WD_ALIGN_PARAGRAPH.CENTER, color=TEXT_SEC)

doc.add_page_break()

# =============================================
# MANAGEMENT SAMENVATTING
# =============================================
doc.add_heading('Management Samenvatting', level=1)

add_para("Dit kennisdossier biedt een uitgebreid inzicht in de PGS 15:2025 compliance-verplichtingen voor Phoenix Metals IJmuiden, specifiek gericht op de opslag van verpakte gevaarlijke stoffen.")
doc.add_paragraph()

add_para("Kernbevindingen:", bold=True)
items = [
    "Phoenix Metals hanteert momenteel 6 gevaarlijke stoffen (totaal ~300 liter / ~390 kg), uitsluitend ADR-klasse 8 (bijtende stoffen) en niet-ADR-goederen.",
    "Het totaal volume zit ver onder alle PGS 15 drempelwaarden. Basisveiligheidsniveau volstaat — geen aanvullend veiligheidsniveau (A/B/C) vereist.",
    "KRITIEK: Natriumhydroxide (base) en Zwavelzuur (zuur) staan momenteel op hetzelfde rack. Dit is niet-compliant met PGS 15 Bijlage E, Tabel 9 (ADR 8 ↔ ADR 8 = A-scheiding vereist).",
]
for item in items:
    add_bullet(item)

doc.add_paragraph()
add_para("Directe actiepunten:", bold=True, color=CRITICAL)
actions = [
    "Scheiden van NaOH en H₂SO₄ in aparte lekbakken met minimaal 2 meter afstand",
    "Calcium oxide apart opslaan van alle zwavelzuurproducten",
    "Vloeistofopvang (lekbakken) installeren voor alle jerrycans (minimaal 110% van grootste verpakking)",
]
for i, a in enumerate(actions, 1):
    add_bullet(f"Actie {i}: {a}")

doc.add_page_break()

# =============================================
# HOOFDSTUK 1: INTRODUCTIE PGS 15:2025
# =============================================
doc.add_heading('1. Introductie PGS 15:2025', level=1)

doc.add_heading('1.1 Doel en Reikwijdte', level=2)
add_para("PGS 15 is de Publicatiereeks Gevaarlijke Stoffen-richtlijn voor de opslag van verpakte gevaarlijke stoffen. De richtlijn biedt een systematiek van doelen en maatregelen om de risico's van opslag van gevaarlijke stoffen te beheersen [1].")
add_para("De huidige versie, PGS 15:2025 versie 1.0 (januari 2025), vervangt de eerdere versies en bevat bijgewerkte veiligheidsniveaus, drempelwaarden en maatregelen [1].")

doc.add_heading('1.2 Juridische Status', level=2)
add_para("PGS 15 heeft een informatieve juridische status. De richtlijn is geen wet op zich, maar fungeert als referentiekader binnen het stelsel van de Omgevingswet:")
items = [
    "Bouwbesluit leefomgeving (Bbl): Brandcompartimentering en constructieve eisen",
    "Besluit kwaliteit leefomgeving (Bkl): Externe veiligheidsafstanden",
    "Besluit activiteiten leefomgeving (Bal): Activiteiten met gevaarlijke stoffen",
    "Arbeidsomstandighedenwet (Arbowet): Zorgplicht, RI&E, werkomstandigheden",
]
for item in items:
    add_bullet(item)
add_para("Bedrijven die onder de Seveso-richtlijn vallen moeten aanvullend voldoen aan NEN-EN-ISO 14001, NEN-EN-ISO 45001 of NTA 8620 [1].")

doc.add_heading('1.3 Toepassingsgebied', level=2)
add_para("PGS 15 is van toepassing op de opslag van verpakte gevaarlijke stoffen die vallen onder ADR-klassen 2 t/m 9 (exclusief klasse 1, 7, en lithiumhoudende energiedragers). De richtlijn geldt voor zowel binnen- als buitenopslag, brandveiligheidsopslagkasten, (tank)containers en tijdelijke opslag [1].")

doc.add_page_break()

# =============================================
# HOOFDSTUK 2: BEDRIJFSPROFIEL
# =============================================
doc.add_heading('2. Bedrijfsprofiel Phoenix Metals', level=1)

doc.add_heading('2.1 Algemeen', level=2)
add_para("Phoenix Metals is gevestigd in IJmuiden en exploiteert een pilotfaciliteit voor metaalverwerking en chemische procesvoering. Het bedrijf verwerkt staalslakken tot vanadium-elektrolyten en hanteert hiervoor een beperkt aantal chemische stoffen [3].")

doc.add_heading('2.2 Chemisch Register', level=2)
add_para("Onderstaande tabel toont het volledige chemisch register zoals gedocumenteerd in de Registration Chemicals MASTER v2.1.0 [3].")

headers = ["#", "Stof", "CAS-nummer", "ADR", "PG", "Volume", "Verpakking", "Locatie"]
rows = [
    ["1", "Sodium hydroxide, 50% in water", "1310-73-2", "8", "II", "100 l (4×25)", "Jerrycan", "Rack front of lab"],
    ["2", "Sulfuric acid, 75% in water", "7664-93-9", "8", "II", "30 l (3×10)", "Jerrycan", "Rack front of lab"],
    ["3", "Sulfuric acid, 50% in water", "7664-93-9", "8", "II", "70 l (7×10)", "Jerrycan", "Rack front of lab"],
    ["4", "Sulfuric acid, 25% in water", "7664-93-9", "8", "II", "100 l (4×25)", "Jerrycan", "Rack front of lab"],
    ["5", "Aluminum sulfate octadecahydrate", "7784-31-8", "N/A", "N/A", "5 kg (2×2.5)", "Canister", "Rack front of lab"],
    ["6", "Calcium oxide", "1305-78-8", "N/A", "N/A", "10 kg (2×5)", "Canister", "Rack front of lab"],
]
add_table(headers, rows)

add_para("Samenvatting:", bold=True)
bullets = [
    "Totaal ADR-klasse 8: 300 liter (4 stoffen)",
    "Totaal niet-ADR: 15 kg (2 stoffen)",
    "SVHC-stoffen: Geen",
    "CMR/CLP-stoffen: Geen",
    "Huidige opslaglocatie: Storage racking — rack in front of lab (één brandcompartiment)",
]
for b in bullets:
    add_bullet(b)

doc.add_heading('2.3 Opslagconfiguratie', level=2)
add_para("Alle stoffen zijn momenteel opgeslagen op een enkel rack (storage racking) direct voor het laboratorium. De jerrycans en canisters zijn ongeopend en in stock. Er is momenteel geen formele scheiding tussen zuren en basen, noch zijn lekbakken gedocumenteerd [3].")

doc.add_page_break()

# =============================================
# HOOFDSTUK 3: VEILIGHEIDSNIVEAUS & DREMPELWAARDEN
# =============================================
doc.add_heading('3. Veiligheidsniveaus en Drempelwaarden', level=1)

doc.add_heading('3.1 Systematiek Veiligheidsniveaus', level=2)
add_para("PGS 15 hanteert een gelaagd systeem van veiligheidsniveaus, gebaseerd op het escalatierisico van de opgeslagen stoffen in combinatie met de hoeveelheid [1]:")

headers = ["Niveau", "Geldigheid", "Aanvullende eisen"]
rows = [
    ["Basisveiligheidsniveau", "ALTIJD van toepassing, ongeacht hoeveelheid", "MW1 zorgplicht + standaard maatregelen"],
    ["Veiligheidsniveau B", "Vanaf specifieke drempelwaarden (meestal 10-20 ton)", "60 min Wbdbo, D6/D10/D11 doelen"],
    ["Veiligheidsniveau A", "Bij hoge hoeveelheden of hoge risico's", "VBB-installatie, branddetectie, D12 doelen"],
    ["Veiligheidsniveau C", "Alleen ADR 2.1 gasflessen", "Verspreiding voorkomen, D7 doelen"],
]
add_table(headers, rows)

doc.add_heading('3.2 Tabel 6 — Criteria Vereist Veiligheidsniveau', level=2)
add_para("Onderstaande tabel toont de relevante drempelwaarden uit PGS 15 Tabel 6 voor de bij Phoenix Metals aanwezige ADR-klassen [1]:")

headers = ["ADR-klasse", "Verpakkingsgroep", "Eigenschap", "< 10 ton", "10-20 ton", "> 20 ton"]
rows = [
    ["8", "I (VP ≤60°C)", "Brandbaar", "Basis + 60 min Wbdbo", "VN-B (D6,D10,D11)", "VN-A (D12)"],
    ["8", "I (>100°C)", "Onbrandbaar", "Basis + 60 min Wbdbo", "Basis + 90 min Wbdbo", "—"],
    ["8", "II+III brandbaar", "Brandbaar", "Basis + 60 min Wbdbo", "VN-B (60 min)", "VN-A"],
    ["8", "II+III onbrandbaar", "Onbrandbaar", "ALLES basisveiligheidsniveau", "—", "—"],
    ["9", "—", "Onbrandbaar", "ALLES basisveiligheidsniveau", "—", "—"],
]
add_table(headers, rows)

doc.add_heading('3.3 Tabel 7 — Grenswaarden', level=2)
add_para("Tabel 7 definieert de ondergrensen waaronder de PGS 15-richtlijn van toepassing is [1]:")

headers = ["ADR-klasse", "Omschrijving", "Grenswaarde"]
rows = [
    ["3 VGI", "Brandbare vloeistoffen, vlampunt tot 60°C", "400 kg"],
    ["6.1 + 8 met etiket 6.1", "Giftige of bijtende stoffen met bijkomend giftigheid", "1.000 kg"],
    ["5.1, 6.1, 8, 9", "Totale hoeveelheid per ADR-klasse", "2.500 kg"],
]
add_table(headers, rows)

doc.add_heading('3.4 Conclusie voor Phoenix Metals', level=2)
add_para("Analyse van de huidige situatie:", bold=True)

headers = ["Parameter", "Phoenix Metals", "Drempelwaarde", "Status"]
rows = [
    ["Totaal ADR 8", "~390 kg", "2.500 kg (Tabel 2)", "✅ Ver onder"],
    ["Veiligheidsniveau A", "0 kg richting >20.000", ">20.000 kg", "✅ Niet van toepassing"],
    ["Veiligheidsniveau B", "0 kg richting >10.000", ">10.000 kg", "✅ Niet van toepassing"],
    ["Vereist Wbdbo", "Niet verplicht", "60 min (vanaf drempel)", "✅ Alleen Bbl-eis"],
    ["Basisveiligheidsniveau", "390 kg", "ALTIJD", "✅ Van toepassing"],
]
add_table(headers, rows)

p = doc.add_paragraph()
run = p.add_run("CONCLUSIE: ")
run.bold = True
run.font.color.rgb = SUCCESS
p.add_run("Phoenix Metals bevindt zich ver onder alle PGS 15-drempelwaarden. Alleen het basisveiligheidsniveau is vereist. Echter: de stoffenscheidingseis (M35, Tabel 9) geldt ONACHTER het veiligheidsniveau en is momenteel NIET compliant.")

doc.add_page_break()

# =============================================
# HOOFDSTUK 4: OPSLAG-COMPATIBILITEITSMATRIX
# =============================================
doc.add_heading('4. Opslag-Compatibiliteitsmatrix', level=1)

doc.add_heading('4.1 Bijlage E — Tabel 9: Onverenigbare Combinaties', level=2)
add_para("PGS 15 Bijlage E definieert welke combinaties van gevaarlijke stoffen gescheiden moeten worden opgeslagen. Tabel 9 kent drie scheidingsniveaus [1]:")

headers = ["Code", "Betekenis", "Methode"]
rows = [
    ["V", "Aparte vakken", "Stoffen in aparte vakken binnen zelfde opslagvoorziening (>10.000 kg)"],
    ["B", "Beoordeel", "Gescheiden opslag tenzij VIB aantoont dat stoffen niet reageren, of beide vaste stoffen. Realisatie via 2 m afstand, aparte lekbakken, of bufferzone"],
    ["A", "Apart brandcompartiment", "Apart brandcompartiment, of 3-zijdige muur (≥30 min brandwerend), of 5 m vrije zone"],
    ["—", "Geen scheiding nodig", "Stoffen mogen gezamenlijk worden opgeslagen"],
]
add_table(headers, rows)

doc.add_heading('4.2 Volledige Matrix Tabel 9', level=2)
add_para("Onderstaand de complete matrix uit PGS 15 Bijlage E, Tabel 9 [1]:")

headers = ["ADR-klasse ↓ / →", "3 (brandbaar)", "5.1 (oxiderend)", "6.1 + CMR", "8 (bijtend)", "9 (milieu)", "Overig"]
rows = [
    ["3 (brandbaar)", "—", "V", "B of V", "B", "B", "—"],
    ["5.1 (oxiderend)", "V", "—", "B of V", "A of V", "B", "—"],
    ["6.1 + CMR", "B of V", "B of V", "B", "A", "B", "—"],
    ["8 (bijtend)", "B", "B", "B", "A", "B", "—"],
    ["9 (milieu)", "B", "B", "B", "A", "B", "—"],
    ["Overig", "—", "—", "—", "A", "—", "—"],
]
add_table(headers, rows)

doc.add_heading('4.3 Phoenix Metals Specifieke Matrix', level=2)
add_para("Relevante combinaties voor de huidige stoffenmix bij Phoenix Metals [1][3]:")

headers = ["Combinatie", "Scheiding vereist?", "Niveau", "Toelichting"]
rows = [
    ["NaOH 50% ↔ H₂SO₄ (alle concentraties)", "JA", "A", "Zuur + base = exotherme reactie. Tabel 9: ADR 8 ↔ ADR 8 = A"],
    ["NaOH 50% ↔ Aluminum sulfate", "Beoordeel", "B", "Base + zout. VIB-consultatie vereist"],
    ["NaOH 50% ↔ Calcium oxide", "Beoordeel", "B", "Base + basisch oxide. Beoordeling vereist"],
    ["H₂SO₄ ↔ H₂SO₄ (verschillende %)", "NEE", "—", "Zelfde stof, zelfde gevarenklasse"],
    ["H₂SO₄ ↔ Aluminum sulfate", "Beoordeel", "B", "Zuur + zout. Beoordeling vereist"],
    ["H₂SO₄ ↔ Calcium oxide", "JA", "A", "Zuur + sterk basisch oxide. Exotherm risico"],
]
add_table(headers, rows)

doc.add_heading('4.4 Praktische Oplossing', level=2)
add_para("Voor opslag <10.000 kg gelden de volgende opties uit Bijlage E, sectie E.3 [1]:")
bullets = [
    "Optie 1: Aparte lekbakken per categorie (zuren / basen / overig)",
    "Optie 2: Minimaal 2 meter vrije afstand tussen de te scheiden stoffen",
    "Optie 3: Bufferzone van 2 meter met stoffen waarvan gezamenlijke opslag is toegelaten",
]
for b in bullets:
    add_bullet(b)

p = doc.add_paragraph()
run = p.add_run("AANBEVOLEN OPLOSSING VOOR PHOENIX METALS: ")
run.bold = True
run.font.color.rgb = PRIMARY
p.add_run("Plaats NaOH 50% in een aparte lekbak, H₂SO₄ (alle concentraties) in een aparte lekbak, en Calcium oxide apart van beide. Markeer de vakken duidelijk. Houd minimaal 2 meter afstand tussen de NaOH-lekbak en de H₂SO₄-lekbak.")

doc.add_page_break()

# =============================================
# HOOFDSTUK 5: BASISVEILIGHEIDSNIVEAU MAATREGELEN
# =============================================
doc.add_heading('5. Basisveiligheidsniveau Maatregelen', level=1)

add_para("Onderstaand de belangrijkste maatregelen uit het basisveiligheidsniveau die van toepassing zijn op Phoenix Metals [1].")

measures = [
    ("MW1", "Zorgplicht Basisveiligheid", "Er is een basisveiligheidsniveau aanwezig dat bestaat uit beschermende maatregelen, bewezen goede praktijken, good housekeeping en goed vakmanschap. Dit is altijd van toepassing.", "⚠️ Toetsen"),
    ("M2", "Opslaan van verpakte gevaarlijke stoffen", "Verpakte gevaarlijke stoffen boven de ondergrenzen worden opgeslagen in een daarvoor bestemde opslagvoorziening. Uitgezonderd: werkvoorraad conform M14.", "⚠️ Toetsen"),
    ("M3", "Vereist veiligheidsniveau", "De opslagvoorziening heeft een veiligheidsniveau volgens Tabel 6. Phoenix Metals: basisveiligheidsniveau volstaat.", "✅ Compliant"),
    ("M14", "Werkvoorraad", "Alleen voor de bedrijfsvoering noodzakelijke stoffen worden aangemerkt als werkvoorraad. Eén aangebroken + één nieuwe verpakkingseenheid per stof.", "⚠️ Toetsen"),
    ("M15", "Maximale omvang opslagvoorziening", "Opslagvoorziening = onafhankelijk brandcompartiment. Zonder VBB: max 1.000 m² (<20 ton).", "✅ Compliant (klein volume)"),
    ("M30", "Vloeistofopvang", "Vloeistofopvang (lekbakken) om vrijkomen van vloeistoffen te voorkomen. Capaciteit minimaal 110% van grootste verpakking.", "❌ Niet gedocumenteerd"),
    ("M35", "Stoffenscheiding", "Onverenigbare combinaties worden gescheiden opgeslagen volgens Tabel 9 (Bijlage E).", "❌ Niet-compliant"),
    ("M36", "Verpakkingsintegriteit", "Verpakkingen zijn in goede staat. Regelmatige controle op beschadiging, veroudering, degradatie.", "⚠️ Toetsen"),
    ("M45", "Correct gebruik verpakking", "Verpakkingen worden correct gebruikt en opgeslagen overeenkomstig de voorschriften.", "⚠️ Toetsen"),
    ("M77/M78", "Fysieke bescherming", "Opslaglocaties zijn voorzien van fysieke bescherming tegen aanrijding (heftruckbeveiliging).", "⚠️ Toetsen"),
    ("M85/M86", "Personeelsdeskundigheid", "Medewerkers zijn voldoende deskundig en getraind. Instructie over gevaren en procedures.", "⚠️ Toetsen"),
    ("M109", "Toegankelijkheid hulpdiensten", "Opslagvoorziening is bereikbaar en toegankelijk voor hulpdiensten.", "⚠️ Toetsen"),
]

headers = ["M-nr", "Maatregel", "Samenvatting", "PM Status"]
rows = [[m[0], m[1], m[2], m[3]] for m in measures]
add_table(headers, rows, col_widths=[2, 4, 8, 3])

doc.add_page_break()

# =============================================
# HOOFDSTUK 6: BRANDPREVENTIE & COMPARTIMENTERING
# =============================================
doc.add_heading('6. Brandpreventie en Compartimentering', level=1)

doc.add_heading('6.1 Doelen', level=2)
add_para("PGS 15 kent de volgende brandgerelateerde doelen [1]:")

headers = ["Doel", "Omschrijving", "Relevant voor PM"]
rows = [
    ["D8", "Voorkomen van ontsteking", "Beheersing ontstekingsbronnen, brandbare materialen, beginnende brand blussen"],
    ["D9", "Voorkomen brand in opslagvoorziening", "Ontstekingsbronbeheersing, blussen beginnende brand"],
    ["D10", "Voorkomen escalatie (passief)", "Compartimenteren, scheiding, brandwerendheid"],
    ["D11", "Voorkomen escalatie (actief)", "Detectie, blusmiddelen, bereikbaarheid hulpdiensten"],
    ["D12", "(Semi-)automatische blussing", "Snel detecteren en blussen — ALLEEN veiligheidsniveau A"],
]
add_table(headers, rows)

doc.add_heading('6.2 Brandwerendheid (Wbdbo)', level=2)
add_para("De vereiste brandwerendheid van de constructie (Wbdbo) is afhankelijk van het veiligheidsniveau [1]:")

headers = ["Veiligheidsniveau", "Minimale Wbdbo", "Geldt voor"]
rows = [
    ["Basis", "Bbl-eis (meestal 20-30 min)", "Alle opslagvoorzieningen"],
    ["VN-B", "60 minuten", "Vanaf drempelwaarden per ADR-klasse"],
    ["VN-A (10-20 ton)", "60-90 minuten", "Hogere hoeveelheden"],
    ["VN-A (>20 ton)", "90+ minuten", "Grootste opslagen"],
]
add_table(headers, rows)

add_para("Voor Phoenix Metals (basisveiligheidsniveau, ~390 kg) is geen verhoogde Wbdbo vereist boven het Bouwbesluit leefomgeving [1].")

doc.add_page_break()

# =============================================
# HOOFDSTUK 7: SCHAALBAARHEIDS-SCENARIO'S
# =============================================
doc.add_heading('7. Schaalbaarheids-Scenario\'s', level=1)

add_para("Onderstaand de fasering van facilitaire eisen bij toename van de opslagcapaciteit van ADR-klasse 8 stoffen [1].")

doc.add_heading('7.1 Fase 1: Tot 10.000 kg (Huidig + Groei)', level=2)
bullets = [
    "Vereist niveau: Basisveiligheidsniveau + 60 min Wbdbo (indien > drempel Tabel 7)",
    "Facilitaire investering: Brandwerende constructie, lekbakken, stoffenscheiding",
    "Compartimentering: Max 1.000 m² zonder VBB-installatie",
    "Detectie: Niet verplicht (aangeraden: branddetectie)",
    "Geschatte investering: €5.000 - €15.000",
]
for b in bullets:
    add_bullet(b)

doc.add_heading('7.2 Fase 2: 10.000 - 20.000 kg', level=2)
bullets = [
    "Vereist niveau: Veiligheidsniveau B (D6, D10, D11)",
    "60 minuten Wbdbo voor alle constructies",
    "Max 1.000 m² brandcompartiment zonder VBB",
    "Aanvullende doelen: D6 (hulpdiensten), D10 (passieve escalatiepreventie), D11 (actieve escalatiepreventie)",
    "Geschatte investering: €25.000 - €75.000",
]
for b in bullets:
    add_bullet(b)

doc.add_heading('7.3 Fase 3: Meer dan 20.000 kg', level=2)
bullets = [
    "Vereist niveau: Veiligheidsniveau A (D12 — semi-automatische blussing)",
    "VBB-installatie verplicht (blussende automatisch werkende brandblusinstallatie)",
    "Branddetectiesysteem met doormelding naar PAC/RAC (M97)",
    "Max 2.500 m² met VBB-installatie",
    "UPD (uitvoeringsplan brandbestrijding) vereist (M99)",
    "Geschatte investering: €100.000 - €300.000+",
]
for b in bullets:
    add_bullet(b)

doc.add_heading('7.4 Overzicht Schaalbaarheid', level=2)

headers = ["Schaal", "Volume ADR 8", "Vereist niveau", "Belangrijkste investering"]
rows = [
    ["Huidig", "~390 kg", "Basisveiligheidsniveau", "Lekbakken + scheiding"],
    ["Fase 1", "<10.000 kg", "Basis + 60 min Wbdbo", "Brandwerende constructie"],
    ["Fase 2", "10-20.000 kg", "VN-B (D6, D10, D11)", "Blusinstallatie + detectie"],
    ["Fase 3", ">20.000 kg", "VN-A (D12)", "VBB + PAC-doormelding"],
]
add_table(headers, rows)

doc.add_page_break()

# =============================================
# HOOFDSTUK 8: COMPLIANCE CHECKLIST
# =============================================
doc.add_heading('8. Compliance Checklist Phoenix Metals', level=1)

add_para("Onderstaand de volledige checklist van PGS 15-maatregelen geïnventariseerd tegen de huidige situatie bij Phoenix Metals [1][3].")

checklist = [
    ("MW1", "Zorgplicht basisveiligheid", "Aantoonbaar basisveiligheidsniveau aanwezig", "⚠️", "Verifiëren met PM"),
    ("M2", "Opslag in bestemde voorziening", "Stoffen in daarvoor bestemde opslag", "⚠️", "Rack = opslagvoorziening? Toetsen"),
    ("M3", "Vereist veiligheidsniveau", "Conform Tabel 6", "✅", "Basis volstaat bij ~390 kg"),
    ("M14", "Werkvoorraad regeling", "Max 1 aangebroken + 1 nieuwe per stof", "⚠️", "Verifiëren met PM"),
    ("M15", "Max oppervlak brandcompartiment", "Zonder VBB: max 1.000 m²", "✅", "Klein volume"),
    ("M20", "Registratie gevaarlijke stoffen", "Actualisatie stoffenlijst", "⚠️", "Register aanwezig, actualiteit toetsen"),
    ("M30", "Vloeistofopvang (lekbakken)", "110% grootste verpakking", "❌", "NIET gedocumenteerd"),
    ("M35", "Stoffenscheiding", "Conform Tabel 9", "❌", "NIET-compliant: NaOH en H₂SO₄ op zelfde rack"),
    ("M36", "Verpakkingsintegriteit", "Regelmatige controle", "⚠️", "Ongeopend = OK, controleregime toetsen"),
    ("M45", "Correct gebruik verpakking", "Juiste hantering", "⚠️", "Toetsen"),
    ("M77", "Fysieke bescherming (botsbeveiliging)", "Bescherming tegen aanrijding", "⚠️", "Toetsen of rack afgeschermd"),
    ("M78", "Fysieke bescherming (stellingen)", "Stellingen stabiel en veilig", "⚠️", "Toetsen"),
    ("M85", "Deskundigheid personeel", "Opleiding + instructie", "⚠️", "Verifiëren met PM"),
    ("M86", "Noodorganisatie", "Noodplan + oefeningen", "⚠️", "Verifiëren met PM"),
    ("M89", "Hulpdienstbereikbaarheid", "Bereikbaar + toegankelijk", "⚠️", "Verifiëren met PM"),
    ("M109", "Bereikbaarheid hulpdiensten", "Bereikbaar en toegankelijk", "⚠️", "Verifiëren met PM"),
]

headers = ["M-nr", "Maatregel", "Vereiste", "Status", "Toelichting"]
add_table(headers, checklist, col_widths=[1.5, 3.5, 4, 1.5, 5])

add_para("Legenda: ✅ = Compliant | ⚠️ = Verifiëren | ❌ = Niet-compliant", bold=True, size=9, color=TEXT_SEC)

doc.add_page_break()

# =============================================
# HOOFDSTUK 9: WETTELIJKE KADERS
# =============================================
doc.add_heading('9. Wettelijke Kaders', level=1)

frameworks = [
    ("PGS 15:2025", "Publicatiereeks Gevaarlijke Stoffen — Opslag verpakte gevaarlijke stoffen", "Primaire richtlijn. Definieert veiligheidsniveaus, drempelwaarden en maatregelen [1]."),
    ("Omgevingswet", "Bouwwerken, activiteiten en milieukwaliteit", "Bbl (brandcompartimentering), Bkl (externe veiligheidsafstanden), Bal (activiteiten met gevaarlijke stoffen) [1]."),
    ("Arbowet", "Arbeidsomstandigheden", "Zorgplicht werkgever, RI&E verplicht, werkomstandigheden bij blootstelling aan gevaarlijke stoffen."),
    ("ADR", "Accord européen relatief au transport international des marchandises Dangereuses par Route", "Classificatiesysteem voor vervoer → basis voor PGS 15 opslagklassen."),
    ("CLP (EG 1272/2008)", "Classification, Labelling and Packaging", "EU-classificatie, etikettering en verpakking van stoffen en mengsels."),
    ("REACH (EG 1907/2006)", "Registration, Evaluation, Authorisation and Restriction of Chemicals", "Registratie, SDS-verplichtingen, risicobeheer. Zie separaat REACH-kennisdossier."),
]

headers = ["Wetgeving", "Volledige naam", "Relevantie Phoenix Metals"]
rows = [[f[0], f[1], f[2]] for f in frameworks]
add_table(headers, rows, col_widths=[3, 5, 8])

doc.add_page_break()

# =============================================
# BIJLAGEN
# =============================================
doc.add_heading('Bijlagen', level=1)

doc.add_heading('Bijlage A: Bronnenlijst', level=2)
sources = [
    "[1] PGS 15:2025 versie 1.0 (januari 2025) — Publicatiereeks Gevaarlijke Stoffen",
    "[2] MASTER_STYLEGUIDE v1.2 — JvG Consultancy",
    "[3] Phoenix Metals — Registration Chemicals MASTER v2.1.0 (november 2024)",
    "[4] Omgevingswet — Bouwbesluit leefomgeving (Bbl)",
    "[5] Arbeidsomstandighedenwet — Arbobesluit art. 4.1c",
    "[6] ADR 2025 — UN Economic Commission for Europe",
    "[7] CLP-Verordening (EG) Nr. 1272/2008",
    "[8] REACH-Verordening (EG) Nr. 1907/2006",
]
for s in sources:
    add_para(s, size=10, color=TEXT_SEC)

doc.add_heading('Bijlage B: Tabel 6 — Volledige Criteria Vereist Veiligheidsniveau', level=2)
add_para("Zie PGS 15:2025, pagina 65-68 voor de volledige tabel. Een samenvatting is opgenomen in Hoofdstuk 3 van dit dossier.", size=10, color=TEXT_SEC)

doc.add_heading('Bijlage C: Tabel 9 — Combinaties ADR-klassen', level=2)
add_para("Zie PGS 15:2025, pagina 194 voor de volledige matrix. Een uitgebreide weergave is opgenomen in Hoofdstuk 4 van dit dossier.", size=10, color=TEXT_SEC)

# === SAVE ===
os.makedirs(os.path.dirname(OUTPUT), exist_ok=True)
doc.save(OUTPUT)
print(f"✅ KENNISDOSSIER OPGESLAGEN: {OUTPUT}")
print(f"   Grootte: {os.path.getsize(OUTPUT):,} bytes")
