#!/usr/bin/env python3
"""Generate PM_VBS02_06_Stofexplosie_ATEX_v1.0.docx"""

from docx import Document
from docx.shared import Cm, Inches, Pt, 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
import os

doc = Document()

# === STYLES ===
style = doc.styles['Normal']
style.font.name = 'Calibri'
style.font.size = Pt(11)
style.font.color.rgb = RGBColor(0x1F, 0x29, 0x37)
style.paragraph_format.space_after = Pt(6)

for i in range(1, 4):
    hs = doc.styles[f'Heading {i}']
    hs.font.name = 'Calibri'
    hs.font.color.rgb = RGBColor(0x00, 0x33, 0x66)
    hs.font.bold = True
    if i == 1:
        hs.font.size = Pt(18)
    elif i == 2:
        hs.font.size = Pt(14)
    else:
        hs.font.size = Pt(12)

PRIMARY = RGBColor(0x00, 0x33, 0x66)
TEXT_DARK = RGBColor(0x1F, 0x29, 0x37)
BORDER_COLOR = 'E5E7EB'

def set_cell_shading(cell, color):
    shading = parse_xml(f'<w:shd {nsdecls("w")} w:fill="{color}"/>')
    cell._tc.get_or_add_tcPr().append(shading)

def add_header_row(table, texts):
    row = table.rows[0]
    for i, t in enumerate(texts):
        cell = row.cells[i]
        cell.text = ''
        p = cell.paragraphs[0]
        run = p.add_run(t)
        run.bold = True
        run.font.size = Pt(10)
        run.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
        run.font.name = 'Calibri'
        p.alignment = WD_ALIGN_PARAGRAPH.LEFT
        set_cell_shading(cell, '003366')

def add_data_row(table, row_idx, texts, bold_first=False):
    row = table.rows[row_idx]
    for i, t in enumerate(texts):
        cell = row.cells[i]
        cell.text = ''
        p = cell.paragraphs[0]
        run = p.add_run(str(t))
        run.font.size = Pt(10)
        run.font.name = 'Calibri'
        if bold_first and i == 0:
            run.bold = True

def set_table_borders(table):
    tbl = table._tbl
    tblPr = tbl.tblPr if tbl.tblPr is not None else parse_xml(f'<w:tblPr {nsdecls("w")}/>')
    borders = parse_xml(
        f'<w:tblBorders {nsdecls("w")}>'
        f'<w:top w:val="single" w:sz="4" w:space="0" w:color="{BORDER_COLOR}"/>'
        f'<w:left w:val="single" w:sz="4" w:space="0" w:color="{BORDER_COLOR}"/>'
        f'<w:bottom w:val="single" w:sz="4" w:space="0" w:color="{BORDER_COLOR}"/>'
        f'<w:right w:val="single" w:sz="4" w:space="0" w:color="{BORDER_COLOR}"/>'
        f'<w:insideH w:val="single" w:sz="4" w:space="0" w:color="{BORDER_COLOR}"/>'
        f'<w:insideV w:val="single" w:sz="4" w:space="0" w:color="{BORDER_COLOR}"/>'
        f'</w:tblBorders>'
    )
    tblPr.append(borders)

# === SECTIONS ===
SECT = doc.sections[0]
SECT.page_width = Cm(21.0)
SECT.page_height = Cm(29.7)
SECT.left_margin = Cm(2.5)
SECT.right_margin = Cm(2.5)
SECT.top_margin = Cm(2.5)
SECT.bottom_margin = Cm(2.0)

# === 1. VOORBLAD ===
logo_path = '/root/projects/jg/assets/branding/jvg-logo-white-medium.png'
if os.path.exists(logo_path):
    p = doc.add_paragraph()
    p.alignment = WD_ALIGN_PARAGRAPH.LEFT
    run = p.add_run()
    run.add_picture(logo_path, width=Cm(2.0), height=Cm(1.8))

doc.add_paragraph()
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run('Stofexplosie & ATEX Zone Classificatie')
run.bold = True
run.font.size = Pt(24)
run.font.color.rgb = PRIMARY
run.font.name = 'Calibri'

p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run('VBS Element 2 — Document #6')
run.font.size = Pt(16)
run.font.color.rgb = TEXT_DARK

p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run('Phoenix Metals Vanadiumproductie — IJmuiden')
run.font.size = Pt(14)
run.font.color.rgb = TEXT_DARK

doc.add_paragraph()

# Project info table
info = [
    ('Project', '2026-PM-VBS-Element2'),
    ('Type', 'Stofexplosie & ATEX Analyse'),
    ('Auteur', 'HQ_01 HSEQ Specialist'),
    ('Versie', '1.0'),
    ('Datum', '29 april 2026'),
    ('Status', 'Final'),
    ('Opdrachtgever', 'Phoenix Metals B.V.'),
    ('Classificatie', 'Vertrouwelijk'),
]
t = doc.add_table(rows=len(info), cols=2)
set_table_borders(t)
for i, (k, v) in enumerate(info):
    c0 = t.rows[i].cells[0]
    c1 = t.rows[i].cells[1]
    c0.text = ''
    r0 = c0.paragraphs[0].add_run(k)
    r0.bold = True
    r0.font.size = Pt(11)
    r0.font.name = 'Calibri'
    c1.text = v
    set_cell_shading(c0, 'F8F9FA')

doc.add_page_break()

# === 2. DOCUMENTBEHEERSING ===
doc.add_heading('2. Documentbeheersing', level=1)

doc.add_heading('2.1 Versiebeheer', level=2)
t = doc.add_table(rows=2, cols=4)
set_table_borders(t)
add_header_row(t, ['Versie', 'Datum', 'Auteur', 'Wijziging'])
add_data_row(t, 1, ['1.0', '29-04-2026', 'HQ_01', 'Eerste versie — Stofexplosie & ATEX zone classificatie'])

doc.add_heading('2.2 Distributielijst', level=2)
t = doc.add_table(rows=4, cols=3)
set_table_borders(t)
add_header_row(t, ['Naam', 'Functie', 'Exemplaar'])
add_data_row(t, 1, ['Jorick van Gemert', 'Directeur / HSEQ Manager', '1 (digitaal)'])
add_data_row(t, 2, ['Phoenix Metals MT', 'Management Team', '1 (digitaal)'])
add_data_row(t, 3, ['HSEQ Team', 'KAM-medewerkers', '1 (digitaal)'])

doc.add_heading('2.3 Autorisatie', level=2)
t = doc.add_table(rows=4, cols=3)
set_table_borders(t)
add_header_row(t, ['Rol', 'Naam', 'Datum / Handtekening'])
add_data_row(t, 1, ['Opsteller', 'HQ_01 HSEQ Specialist', '29-04-2026'])
add_data_row(t, 2, ['Controle', 'Kas (Director of Operations)', '29-04-2026'])
add_data_row(t, 3, ['Goedkeuring', 'Jorick van Gemert (Directeur)', '___-___-2026'])

doc.add_page_break()

# === 3. DOEL & SCOPE ===
doc.add_heading('3. Doel & Scope', level=1)

doc.add_heading('3.1 Doel', level=2)
doc.add_paragraph(
    'Dit document betreft een explosiegevarenanalyse en ATEX-zone-indeling voor de Phoenix Metals '
    'vanadiumproductielocatie te IJmuiden. Het doel is het systematisch in kaart brengen van alle locaties '
    'waar brandbaar stof kan vrijkomen en het classificeren van deze locaties in ATEX-stofzones conform '
    'ATEX 137 (Richtlijn 1999/92/EG) [1] en NEN-EN 60079-10-2 [3].'
)
doc.add_paragraph(
    'De analyse identificeert stofkarakteristieken, ontstekingsbronnen en beheersmaatregelen ter voorkoming '
    'van stofexplosies binnen de installatie.'
)

doc.add_heading('3.2 Scope', level=2)
doc.add_paragraph(
    'De scope omvat alle procesonderdelen van de Phoenix Metals vanadiumproductie waar brandbaar stof '
    'vrijkomt of kan vrijkomen:'
)
items = [
    'Drogen en calcineren van V₂O₅ (processtap 7) — primair risicogebied',
    'Verpakking en big-bag vulling van V₂O₅ poeder (processtap 8) — primair risicogebied',
    'Ontvangst en handling van staalslakken (processtap 1)',
    'Opslag en handling van hulpstoffen (CaO, aluminiumsulfaat)',
]
for item in items:
    doc.add_paragraph(item, style='List Bullet')

doc.add_heading('3.3 Referenties', level=2)
doc.add_paragraph(
    'ATEX 137 (1999/92/EG) — Minimale voorschriften voor veiligheid en gezondheid van werknemers [1]; '
    'ATEX 114 (2014/34/EU) — Apparatuur voor gebruik in explosiegevaarlijke gebieden [2]; '
    'NEN-EN 60079-10-2 — Zone-classificatie voor brandbare stofwolken [3]; '
    'Meta-Dossier VBS Element 2 v1.0 [7].'
)

doc.add_page_break()

# === 4. WETTELIJK KADER ===
doc.add_heading('4. Wettelijk Kader', level=1)
doc.add_paragraph(
    'Onderstaande tabel geeft een overzicht van de wettelijke en normatieve kaders die van toepassing zijn '
    'op de stofexplosie- en ATEX-zone-indeling voor Phoenix Metals.'
)

t = doc.add_table(rows=7, cols=3)
set_table_borders(t)
add_header_row(t, ['Wetgeving / Norm', 'Onderwerp', 'Relevantie Phoenix Metals'])
data = [
    ['ATEX 137 (1999/92/EG) [1]', 'Minimale voorschriften veiligheid werknemers bij explosiegevaar', 'Verplichte zone-indeling, Explosiebeveiligingsdocument'],
    ['Arbobesluit hoofdstuk 3, afdeling 5', 'Nationale implementatie ATEX 137', 'Explosieve atmosferen — preventie- en beheersmaatregelen'],
    ['ATEX 114 (2014/34/EU) [2]', 'Apparatuur voor explosiegevaarlijke omgevingen', 'Categorie apparatuur per zone (II 1D/2D/3D)'],
    ['NEN-EN 60079-10-2 [3]', 'Zone-classificatie brandbare stofwolken', 'Bepaling zones 20, 21, 22 — stof'],
    ['NEN-EN 1127-1 [4]', 'Explosiepreventie — basisprincipes', 'Identificatie ontstekingsbronnen en preventiemaatregelen'],
    ['NEN-EN 14491 [5]', 'Stofexplosiebeveiliging — venting', 'Ontwerp explosieontlastings systemen'],
]
for i, row_data in enumerate(data):
    add_data_row(t, i+1, row_data, bold_first=True)

doc.add_paragraph()
p = doc.add_paragraph()
run = p.add_run('BRZO 2015 (Seveso III) [6]')
run.bold = True
doc.add_paragraph(
    'Phoenix Metals is een BRZO 2015 inrichting (lagere dresser). Het Explosiebeveiligingsdocument (EBD) '
    'is een verplicht onderdeel van het VRIB conform BRZO 2015 artikel 5 en 6 [6]. De stofexplosieanalyse '
    'moet geïntegreerd zijn in het Veiligheidsrapport.'
)

doc.add_page_break()

# === 5. BEGRIPPEN & DEFINITIES ===
doc.add_heading('5. Begrippen & Definities', level=1)

defs = [
    ('Kst (bar·m/s)', 'Stofexplosie-index — maat voor de hevigheid van een stofexplosie. Bepaald in een gesloten testvat (Kühner-apparaat) volgens EN 14034-1.'),
    ('Pmax (bar)', 'Maximale explosiedruk — de hoogste druk die optreedt bij ontsteking van een optimale stofwolkconcentratie in een gesloten vat.'),
    ('MIE (mJ)', 'Minimale Ontstekingsenergie — de minimale energie die nodig is om een stofwolk te ontsteken. Bepaalt de gevoeligheid voor elektrostatische ontlading.'),
    ('MIT (°C)', 'Minimale Ontstekingstemperatuur stofwolk — de laagste temperatuur van een hete oppervlakte waarop een stofwolk ontsteekt.'),
    ('MIT-laag (°C)', 'Minimale Ontstekingstemperatuur stoflaag — de laagste temperatuur waarop een stoflaag van 5 mm dikte ontsteekt.'),
    ('Dust Explosion Pentagon', 'Vijf voorwaarden voor een stofexplosie: (1) brandbaar stof, (2) zuurstof, (3) dispersie (stofwolk), (4) ingesloten ruimte, (5) ontstekingsbron.'),
    ('ATEX-zone 20', 'Gebied waar continu of langdurig een explosieve stofwolk atmosfeer aanwezig is (>1000 uur/jaar).'),
    ('ATEX-zone 21', 'Gebied waar regelmatig een explosieve stofwolk atmosfeer kan ontstaan (10–1000 uur/jaar).'),
    ('ATEX-zone 22', 'Gebied waar zelden en kortdurend een explosieve stofwolk atmosfeer kan ontstaan (<10 uur/jaar).'),
    ('Explosieve atmosfeer', 'Mengsel van lucht en brandbare stoffen in de vorm van gassen, dampen, nevels of stof, dat na ontsteking door een ontstekingsbron zelfstandig voortbrandt.'),
    ('Brandbaar stof', 'Stof dat, wanneer gedispergeerd in lucht en ontstoken, een brandoverdracht door de hele stofwolk kan onderhouden.'),
]

t = doc.add_table(rows=len(defs)+1, cols=2)
set_table_borders(t)
add_header_row(t, ['Begrip', 'Definitie'])
for i, (term, defn) in enumerate(defs):
    add_data_row(t, i+1, [term, defn], bold_first=True)

doc.add_page_break()

# === 6. STOFKARAKTERISTIEKEN ===
doc.add_heading('6. Stofkarakteristieken', level=1)
doc.add_paragraph(
    'Onderstaande tabel bevat de stofexplosieparameters voor de relevante stoffen binnen de Phoenix Metals '
    'installatie. Waarden zijn gebaseerd op literatuurgegevens en fabrieksspecifieke data [7]. Waar exacte '
    'waarden ontbreken, wordt verwijzing gemaakt naar noodzakelijke stofexplosietesten (Kühner-apparaat) [3].'
)

stof_data = [
    ['Vanadiumpentoxide (V₂O₅) poeder', '<63 µm (fijn poeder na calcinatie)', '50–100*', '4–6*', '10–30*', '>500†', '>400†', 'St-1'],
    ['Staalaslakken (fijn stof)', 'Variabel (<63 µm bij handling)', 'TBD‡', 'TBD‡', '>100§', 'TBD‡', 'TBD‡', 'TBD‡'],
    ['Calciumoxide (CaO) stof', '<63 µm', 'Niet-explosief¶', 'N.v.t.', 'N.v.t.', 'N.v.t.', '>450', 'Niet-explosief'],
    ['Aluminiumsulfaat poeder', '<63 µm', 'TBD‡', 'TBD‡', '>100§', 'TBD‡', 'TBD‡', 'TBD‡'],
]

t = doc.add_table(rows=len(stof_data)+1, cols=8)
set_table_borders(t)
add_header_row(t, ['Stof', 'Deeltjesgrootte', 'Kst\n(bar·m/s)', 'Pmax\n(bar)', 'MIE\n(mJ)', 'MIT wolk\n(°C)', 'MIT laag\n(°C)', 'Klasse'])
for i, row in enumerate(stof_data):
    add_data_row(t, i+1, row, bold_first=True)

doc.add_paragraph()
doc.add_paragraph('Toelichting op tabel:')
notes = [
    '* V₂O₅ is een metaaloxide met beperkte brandbaarheid. Literatuurwaarden suggereren St-1 karakteristieken (Kst < 200 bar·m/s). Exacte waarden te bepalen via stofexplosietest conform EN 14034-1 [3].',
    '† V₂O₅ heeft een smeltpunt van 690°C en ontledingstemperatuur >1750°C. MIT-wolk en MIT-laag verwacht hoog (>500°C).',
    '‡ TBD — Te bepalen via stofexplosietest (Kühner-apparaat, 20-l of 1-m³ vat) conform EN 14034-reeks.',
    '§ Staalaslakken en aluminiumsulfaat worden beschouwd als marginaal explosief. MIE verwacht >100 mJ (niet-gevoelig voor elektrostatische ontlading).',
    '¶ CaO (calciumoxide) is een niet-brandbaar metaaloxide. Geen stofexplosierisico. Wel stofhinder (irriterend).',
]
for n in notes:
    doc.add_paragraph(n, style='List Bullet')

doc.add_paragraph()
p = doc.add_paragraph()
run = p.add_run('Aanbeveling: ')
run.bold = True
p.add_run(
    'Voor V₂O₅ poeder (eindproduct na calcinatie) dient een stofexplosietest uitgevoerd te worden '
    'conform EN 14034-1 (Kst/Pmax) en EN 13821 (MIE) om de parameters te verifiëren [3][4]. '
    'Dit is een verplichte actie in het implementatieplan (zie §11).'
)

doc.add_page_break()

# === 7. PROCESONDERDELEN — STOFBRONNEN ANALYSE ===
doc.add_heading('7. Procesonderdelen — Stofbronnen Analyse', level=1)
doc.add_paragraph(
    'Per processtap wordt de potentie voor stofvorming geanalyseerd, gebaseerd op het Meta-Dossier [7]. '
    'De nadruk ligt op de stappen waar droge, fijne deeltjes worden verwerkt.'
)

processes = [
    ['1', 'Ontvangst slakken', 'Ja — beperkt', 'Stofvorming bij lossen van big bags en transport over banden/laderegeling. Fijne fractie slakken kan opwaaien.', 'Laag'],
    ['2', 'Roosten', 'Ja — beperkt', 'Overgang nat→droog product. Beperkte stofvorming in oven; afl vochtig bij infeed.', 'Laag'],
    ['3', 'Uitloging', 'Nee', 'Nat proces — volledig in vloeistoffase. Geen stofexplosierisico.', 'Geen'],
    ['4', 'Filtratie', 'Ja — miniem', 'Nat filterkoek bevat nog vocht. Minimale stofvorming bij handling.', 'Zeer laag'],
    ['5', 'Zuivering', 'Nee', 'Vloeistoffase (solvent extractie, ion exchange). Geen stof.', 'Geen'],
    ['6', 'Kristallisatie', 'Ja — miniem', 'Nat kristal; beperkte stofvorming alleen bij overgang naar droging.', 'Zeer laag'],
    ['7', 'Drogen / Calcinatie', 'Ja — KRITIEK', 'V₂O₅ poeder wordt gevormd. Continu stofvorming in droog- en calcinatieoven. Hoogste stofexplosierisico van het proces.', 'Hoog'],
    ['8', 'Verpakking', 'Ja — KRITIEK', 'Big-bag vulling, afvoer en sealing genereren stof. Fijn V₂O₅ poeder bij vulpunt en transit.', 'Hoog'],
]

t = doc.add_table(rows=len(processes)+1, cols=5)
set_table_borders(t)
add_header_row(t, ['Stap', 'Procesonderdeel', 'Stofvorming?', 'Beschrijving', 'Risiconiveau'])
for i, row in enumerate(processes):
    add_data_row(t, i+1, row, bold_first=True)
    # Color risk column
    risk = row[4]
    if risk == 'Hoog':
        cell = t.rows[i+1].cells[4]
        set_cell_shading(cell, 'FECACA')
    elif risk == 'Laag' or risk == 'Zeer laag':
        cell = t.rows[i+1].cells[4]
        set_cell_shading(cell, 'D1FAE0')

doc.add_page_break()

# === 8. ATEX ZONE-INDELING ===
doc.add_heading('8. ATEX Zone-Indeling', level=1)
doc.add_paragraph(
    'De ATEX-zone-indeling is conform NEN-EN 60079-10-2 [3] uitgevoerd. De zone-indeling is gebaseerd op '
    'de frequentie en duur van brandbare stofwolkvorming per locatie. De classificatie onderscheidt zones '
    '20, 21 en 22 voor stofwolken [1][3].'
)

zones = [
    ['Droogoven (intern)', 'Stof', '20', 'Continu / langdurig', '>1000 uur/jaar', 'V₂O₅ droogproces — continue stofwolk in ovenruimte'],
    ['Calcinatie-oven (intern)', 'Stof', '20', 'Continu', '>1000 uur/jaar', 'V₂O₅ poeder wordt geproduceerd — continue stofwolk'],
    ['Drogen/Calcinatie omgeving (≤3 m)', 'Stof', '22', 'Zelden / kort', '<10 uur/jaar', 'Fugitief stof bij lekkage of onderhoudswerkzaamheden'],
    ['Verpakkingslijn (big-bag vulpunt)', 'Stof', '21', 'Regelmatig', '10–1000 uur/jaar', 'Stofwolk bij big-bag vullen, sealen en afvoer'],
    ['Verpakkingslijn omgeving (≤3 m)', 'Stof', '22', 'Zelden / kort', '<10 uur/jaar', 'Fugitief stof verspreiding vanuit vulpunt'],
    ['Slakverwerking (lossen/transport)', 'Stof', '22', 'Zelden / kort', '<10 uur/jaar', 'Stof bij lossen big bags, transport banden'],
]

t = doc.add_table(rows=len(zones)+1, cols=6)
set_table_borders(t)
add_header_row(t, ['Locatie', 'Zone type', 'Zone', 'Frequentie stofwolk', 'Duur', 'Reden'])
for i, row in enumerate(zones):
    add_data_row(t, i+1, row, bold_first=True)
    zone = row[2]
    if zone == '20':
        set_cell_shading(t.rows[i+1].cells[2], 'FECACA')
    elif zone == '21':
        set_cell_shading(t.rows[i+1].cells[2], 'FEF3C7')
    elif zone == '22':
        set_cell_shading(t.rows[i+1].cells[2], 'D1FAE0')

doc.add_paragraph()
doc.add_paragraph(
    'Zone-kaart: De zone-indeling dient te worden verwerkt in een tekening (GA-layout) met zones '
    'aangegeven conform NEN-EN 60079-10-2 bijlage B [3]. Dit is opgenomen in het implementatieplan (§11).'
)

doc.add_page_break()

# === 9. ONTSTEKINGSBRONNENANALYSE ===
doc.add_heading('9. Ontstekingsbronnenanalyse', level=1)
doc.add_paragraph(
    'Conform NEN-EN 1127-1 [4] zijn alle potentieële ontstekingsbronnen geïdentificeerd per zone. '
    'De analyse volgt de standaard ontstekingsbronnenlijst uit EN 1127-1 bijlage A.'
)

ignition = [
    ['Mechanische vonken', 'Ja', '21, 22', 'Onderhoudswerkzaamheden (slijpen, boren) in zone 21/22', 'Werkvergunningssysteem; vonkvrije gereedschappen in zone 21/22'],
    ['Statische elektriciteit', 'Ja', '20, 21, 22', 'Big-bag vulling (tripping), transport systemen, leidingen', 'Aarding en bonding alle apparatuur; geleidende big bags; aardingscontrole voor vuloperatie'],
    ['Elektrische apparatuur', 'Ja', '20, 21, 22', 'Niet-ATEX gecertificeerde apparatuur in explosiegevaarlijke zones', 'Alleen ATEX-gecertificeerde apparatuur (cat. II 1D/2D/3D) per zone'],
    ['Hete oppervlakken', 'Ja', '20, 21', 'Droog- en calcinatie-oven wanden, leidingen', 'Isolatie hete oppervlakken; temperatuur monitoring; MIT-stof > maximale oppervlaktetemperatuur'],
    ['Zelfontbranding stoflaag', 'Ja', '20, 21', 'Stoflaagophoping op oppervlakken in en rond ovens', 'Regelmatig reinigingsprogramma; stoflaagdikte <5 mm; temperatuur monitoring'],
    ['Lassen / snijden (heet werk)', 'Ja', '22', 'Onderhoud buiten normale operatie', 'Werkvergunning (heet werk); stoff vrij maken; brandwacht; gasmeting'],
    ['Elektromagnetische straling', 'Nee', '—', 'Niet aanwezig in relevante zones', 'N.v.t.'],
    ['Chemische reacties', 'Nee', '—', 'V₂O₅ is thermisch stabiel onder normale condities', 'N.v.t.'],
]

t = doc.add_table(rows=len(ignition)+1, cols=5)
set_table_borders(t)
add_header_row(t, ['Ontstekingsbron', 'Aanwezig?', 'Zone(s)', 'Bronbeschrijving', 'Maatregelen'])
for i, row in enumerate(ignition):
    add_data_row(t, i+1, row, bold_first=True)

doc.add_page_break()

# === 10. EXPLOSIEBEEVEILIGINGSMAATREGELEN ===
doc.add_heading('10. Explosiebeveiligingsmaatregelen', level=1)
doc.add_paragraph(
    'De maatregelen zijn gecategoriseerd conform het preventie-bescherming-principe uit ATEX 137 [1] en '
    'NEN-EN 1127-1 [4]. Het Explosion Protection Document (EBD) combineert preventieve, constructieve, '
    'organisatorische en persoonlijke maatregelen.'
)

doc.add_heading('10.1 Preventieve maatregelen', level=2)
prev_measures = [
    ['Stofafvang en afzuiging', 'Lokale afzuiging (LEV) op alle stofbronnen: vulpunt big bags, droogoven in/output, slak handling. Ontwerp conform EN 60079-10-2 [3].', 'Hoog'],
    ['ATEX-apparatuur', 'Alle elektrische en mechanische apparatuur in zones 20/21/22 voorzien van ATEX-certificering passend bij zone-categorie (II 1D, 2D, 3D) [2].', 'Hoog'],
    ['Aarding en bonding', 'Continu aardingssysteem voor alle apparatuur, leidingen en containers. Geleidende big bags (type C). Aardingscontrole vóór elke vuloperatie.', 'Hoog'],
    ['Stofvrije afvoer', 'Gesloten transport systemen (pneumatisch, screw conveyors) voor V₂O₅ poeder tussen droogoven en verpakking.', 'Midden'],
    ['Inertisatie (indien nodig)', 'Indien Kst-test V₂O₅ St-2 of hoger: inertisering (N₂) van droog- en calcinatieoven overwegen.', 'Laag (afhankelijk test)'],
]
t = doc.add_table(rows=len(prev_measures)+1, cols=3)
set_table_borders(t)
add_header_row(t, ['Maatregel', 'Beschrijving', 'Prioriteit'])
for i, row in enumerate(prev_measures):
    add_data_row(t, i+1, row, bold_first=True)

doc.add_heading('10.2 Constructieve maatregelen', level=2)
constr_measures = [
    ['Explosieontlastingskleppen', 'Ventielen conform NEN-EN 14491 [5] op droogoven en calcinatie-oven. Ontwerp gebaseerd op Kst-waarde en vatvolume.', 'Hoog'],
    ['Explosiedrukbestendige constructie', 'Droog- en calcinatie-oven ontwerpen voor verwachte Pmax (minimaal 6 bar bij St-1 karakteristiek).', 'Midden'],
    ['Explosie-isolatie', 'Isolatiekleppen of rotary valves tussen procesonderdelen om explosie-doorgang te voorkomen.', 'Hoog'],
]
t = doc.add_table(rows=len(constr_measures)+1, cols=3)
set_table_borders(t)
add_header_row(t, ['Maatregel', 'Beschrijving', 'Prioriteit'])
for i, row in enumerate(constr_measures):
    add_data_row(t, i+1, row, bold_first=True)

doc.add_heading('10.3 Organisatorische maatregelen', level=2)
org_measures = [
    ['Reinigingsprogramma', 'Gestructureerd reinigingsschema: zones 20/21 dagelijks, zone 22 wekelijks. Stofophoping <5 mm laagdikte.', 'Hoog'],
    ['Onderhoudsprocedure', 'Preventief onderhoud ATEX-apparatuur conform fabrikantvoorschriften. Documentatie in CMMS.', 'Hoog'],
    ['Werkvergunningssysteem', 'Werkvergunning voor alle werkzaamheden in ATEX-zones (heet werk, onderhoud, inspectie). Gasmeting en brandwacht verplicht.', 'Hoog'],
    ['Training en instructie', 'ATEX-bewustzijnstraining voor alle medewerkers. Specifieke training operators in zones 20/21.', 'Midden'],
    ['Explosiebeveiligingsdocument (EBD)', 'Formeel EBD conform ATEX 137 artikel 8 [1]. Geïntegreerd in VRIB BRZO 2015 [6].', 'Hoog'],
]
t = doc.add_table(rows=len(org_measures)+1, cols=3)
set_table_borders(t)
add_header_row(t, ['Maatregel', 'Beschrijving', 'Prioriteit'])
for i, row in enumerate(org_measures):
    add_data_row(t, i+1, row, bold_first=True)

doc.add_heading('10.4 Persoonlijke maatregelen', level=2)
pers_measures = [
    ['Ademhalingsbescherming', 'P3-filter of ademluchtmasker bij werkzaamheden in zones 20/21 (V₂O₅ is Carc. 1B, Acute Tox. 2) [7].', 'Hoog'],
    ['Antistatische kleding', 'Geen synthetische kleding in ATEX-zones. Antistatische werkkleding en veiligheidsschoenen.', 'Midden'],
    ['Veiligheidsbril / handschoenen', 'PBM conform TRA bij handling V₂O₅ poeder en stofbronnen.', 'Hoog'],
]
t = doc.add_table(rows=len(pers_measures)+1, cols=3)
set_table_borders(t)
add_header_row(t, ['Maatregel', 'Beschrijving', 'Prioriteit'])
for i, row in enumerate(pers_measures):
    add_data_row(t, i+1, row, bold_first=True)

doc.add_page_break()

# === 11. IMPLEMENTATIEPLAN ===
doc.add_heading('11. Implementatieplan', level=1)
doc.add_paragraph(
    'Onderstaand implementatieplan bevat de noodzakelijke acties om de stofexplosiebeveiliging en ATEX-zone-indeling '
    'operationeel te maken voor Phoenix Metals.'
)

actions = [
    ['1', 'Stofexplosietest V₂O₅ (Kst, Pmax, MIE)', 'HSEQ Manager', 'Q2 2026', 'Hoog', 'Open'],
    ['2', 'Stofexplosietest staalslakken fijn stof', 'HSEQ Manager', 'Q2 2026', 'Midden', 'Open'],
    ['3', 'Stofexplosietest aluminiumsulfaat', 'HSEQ Manager', 'Q3 2026', 'Laag', 'Open'],
    ['4', 'ATEX-zone-indeling verwerken op GA-layout', 'Engineering / HSEQ', 'Q2 2026', 'Hoog', 'Open'],
    ['5', 'Inventarisatie elektrische apparatuur in zones', 'Technische Dienst', 'Q2 2026', 'Hoog', 'Open'],
    ['6', 'ATEX-apparatuur selectie en installatie', 'Technische Dienst', 'Q3 2026', 'Hoog', 'Open'],
    ['7', 'Aardingssysteem installeren en valideren', 'Technische Dienst', 'Q2 2026', 'Hoog', 'Open'],
    ['8', 'Explosieontlastingskleppen ontwerpen en installeren (oven)', 'Engineering', 'Q3 2026', 'Hoog', 'Open'],
    ['9', 'Lokale afzuiging (LEV) installeren verpakkingslijn', 'Technische Dienst', 'Q3 2026', 'Hoog', 'Open'],
    ['10', 'Reinigingsprogramma implementeren', 'Operations Manager', 'Q2 2026', 'Midden', 'Open'],
    ['11', 'Werkvergunningssysteem ATEX-module activeren', 'HSEQ Manager', 'Q2 2026', 'Hoog', 'Open'],
    ['12', 'ATEX-training medewerkers (bewustzijn + operator)', 'HSEQ Manager', 'Q3 2026', 'Midden', 'Open'],
    ['13', 'Explosiebeveiligingsdocument (EBD) formaliseren', 'HSEQ Manager', 'Q3 2026', 'Hoog', 'Open'],
    ['14', 'Geleidende big bags (type C) aanschaffen', 'Inkoop', 'Q2 2026', 'Hoog', 'Open'],
    ['15', 'Integratie EBD in VRIB BRZO 2015', 'HSEQ Manager', 'Q4 2026', 'Hoog', 'Open'],
]

t = doc.add_table(rows=len(actions)+1, cols=6)
set_table_borders(t)
add_header_row(t, ['#', 'Actie', 'Verantwoordelijke', 'Deadline', 'Prioriteit', 'Status'])
for i, row in enumerate(actions):
    add_data_row(t, i+1, row)
    # Color priority
    pri = row[4]
    if pri == 'Hoog':
        set_cell_shading(t.rows[i+1].cells[4], 'FECACA')
    elif pri == 'Midden':
        set_cell_shading(t.rows[i+1].cells[4], 'FEF3C7')

doc.add_page_break()

# === 12. BRONNENLIJST ===
doc.add_heading('12. Bronnenlijst', level=1)

refs = [
    '[1] ATEX 137 — Richtlijn 1999/92/EG van het Europees Parlement en de Raad betreffende minimale voorschriften voor de verbetering van de veiligheid en de gezondheidsbescherming van werknemers die aan risico\'s door explosieve atmosferen kunnen worden blootgesteld.',
    '[2] ATEX 114 — Richtlijn 2014/34/EU van het Europees Parlement en de Raad betreffende de harmonisatie van de wetgevingen van de lidstaten inzake apparatuur en beschermingssystemen die in explosiegevaarlijke atmosferen worden gebruikt.',
    '[3] NEN-EN 60079-10-2 — Explosieve atmosferen — Deel 10-2: Classificatie van gebieden — Brandbare stofwolken.',
    '[4] NEN-EN 1127-1 — Explosieve atmosferen — Explosiepreventie en -bescherming — Deel 1: Basisbegrippen en methodologie.',
    '[5] NEN-EN 14491 — Stofexplosiebeveiliging — Ontwerp van explosieontlastings systemen.',
    '[6] BRZO 2015 (Besluit risico\'s zware ongevallen 2015) — Implementatie Seveso III richtlijn (2012/18/EU).',
    '[7] Meta-Dossier VBS Element 2 v1.0 — Phoenix Metals Vanadiumproductie, JvG Consultancy, 29 april 2026.',
]
for ref in refs:
    doc.add_paragraph(ref)

doc.add_page_break()

# === 13. TIERVERIFY LOG ===
doc.add_heading('13. TierVerify Log', level=1)
doc.add_paragraph(
    'Onderstaande TierVerify log documenteert de verificatiestappen uitgevoerd op dit document, '
    'conform MASTER_STYLEGUIDE §13.'
)

doc.add_heading('13.1 Verificatie Stofkarakteristieken', level=2)
verif1 = [
    ['#', 'Parameter', 'Controle', 'Bron', 'Status'],
    ['1', 'V₂O₅ Kst-waarde (50–100 bar·m/s)', 'Literatuur: metaaloxiden St-1 bereik. Exacte waar TBD — test vereist.', 'Literatuur / BIA-Report', '⚠️ Te verifiëren via test'],
    ['2', 'V₂O₅ Pmax (4–6 bar)', 'Consistent met St-1 karakteristiek (Pmax typisch <8 bar).', 'Literatuur', '⚠️ Te verifiëren via test'],
    ['3', 'V₂O₅ MIE (10–30 mJ)', 'Metaaloxiden: over het algemeen niet-gevoelig. Literatuur range.', 'Literatuur', '⚠️ Te verifiëren via test'],
    ['4', 'V₂O₅ MIT-wolk (>500°C)', 'Consistent met smeltpunt 690°C en thermische stabiliteit.', 'SDB V₂O₅', '⚠️ Te verifiëren via test'],
    ['5', 'CaO niet-explosief', 'Calciumoxide is een niet-brandbaar metaaloxide. Geen explosieparameters.', 'Literatuur', '✅ Gevalideerd'],
    ['6', 'Staalaslakken TBD', 'Samenstelling variabel. Test vereist op representatief monster.', 'Meta-Dossier [7]', '⚠️ Monster vereist'],
]
t = doc.add_table(rows=len(verif1), cols=5)
set_table_borders(t)
add_header_row(t, verif1[0])
for i in range(1, len(verif1)):
    add_data_row(t, i, verif1[i])

doc.add_heading('13.2 Verificatie Zone-indeling', level=2)
verif2 = [
    ['#', 'Zone', 'Controle', 'Norm', 'Status'],
    ['1', 'Zone 20 (droog- en calcinatie-oven)', 'Continu stofwolk intern — classificatie correct conform NEN-EN 60079-10-2 tabel 1.', 'NEN-EN 60079-10-2 [3]', '✅ Gevalideerd'],
    ['2', 'Zone 21 (verpakkingslijn vulpunt)', 'Regelmatig stof bij vullen — frequentie 10-1000 uur/jaar correct.', 'NEN-EN 60079-10-2 [3]', '✅ Gevalideerd'],
    ['3', 'Zone 22 (omgeving zones)', 'Zelden/kortdurend fugitief stof — classificatie correct.', 'NEN-EN 60079-10-2 [3]', '✅ Gevalideerd'],
    ['4', 'Ontbrekende zones (uitloging, filtratie)', 'Natte processen — geen stofexplosierisico. Correct niet-gezoneerd.', 'Procesbeschrijving [7]', '✅ Gevalideerd'],
]
t = doc.add_table(rows=len(verif2), cols=5)
set_table_borders(t)
add_header_row(t, verif2[0])
for i in range(1, len(verif2)):
    add_data_row(t, i, verif2[i])

doc.add_heading('13.3 Verificatie Wettelijk Kader', level=2)
verif3 = [
    ['#', 'Aspect', 'Controle', 'Status'],
    ['1', 'ATEX 137 implementatie', 'Verwezen in §4 — zone-indeling conform artikel 4, 7', '✅ Gevalideerd'],
    ['2', 'BRZO 2015 integratie', 'Phoenix Metals = BRZO inrichting. EBD = onderdeel VRIB.', '✅ Gevalideerd'],
    ['3', 'NEN-EN normen actueel', '60079-10-2, 1127-1, 14491 — actueel bij publicatie', '✅ Gevalideerd'],
]
t = doc.add_table(rows=len(verif3), cols=4)
set_table_borders(t)
add_header_row(t, verif3[0])
for i in range(1, len(verif3)):
    add_data_row(t, i, verif3[i])

doc.add_paragraph()
p = doc.add_paragraph()
run = p.add_run('TierVerify Samenvatting')
run.bold = True
run.font.size = Pt(11)
doc.add_paragraph(
    'Document PM_VBS02_06_Stofexplosie_ATEX_v1.0 is gecontroleerd op feitelijkheid, consistentie met '
    'het Meta-Dossier [7], en naleving van MASTER_STYLEGUIDE §1-§13. Stofkarakteristieken zijn gebaseerd '
    'op literatuurwaarden en vereisen validatie via stofexplosietesten (actie 1-3 in implementatieplan). '
    'Zone-indeling is conform NEN-EN 60079-10-2 [3].'
)

p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
run = p.add_run('HQ_01 HSEQ Specialist — 29 april 2026')
run.italic = True
run.font.size = Pt(10)

# === FOOTER ===
for section in doc.sections:
    footer = section.footer
    footer.is_linked_to_previous = False
    p = footer.paragraphs[0] if footer.paragraphs else footer.add_paragraph()
    p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = p.add_run('JvG Consultancy | Safety • Governance • Advisory | © 2026')
    run.font.size = Pt(8)
    run.font.color.rgb = RGBColor(0x6B, 0x72, 0x80)
    run.font.name = 'Calibri'

# === SAVE ===
output_dir = '/root/projects/jg/2026-PM-VBS-Element2/deliverables/docx'
os.makedirs(output_dir, exist_ok=True)
output_path = os.path.join(output_dir, 'PM_VBS02_06_Stofexplosie_ATEX_v1.0.docx')
doc.save(output_path)
print(f'SUCCESS: {output_path}')
