# ============================================================
# MODULE: Quick-Scan Tools & Compliance Bestuur — FASE 3
# HSEQ Intelligence Dashboard
# BRZO Quick Scan, Seveso Self-Assessment, Arbo Checklist,
# MIR Checklist, Compliance Dashboard UI, Document Generators
# ============================================================

import json
import sqlite3
from datetime import datetime, date
from flask import jsonify, request, render_template_string
from indexer import DB_PATH
from search import get_db


# ─── DB Init ───────────────────────────────────────────────────────────────

def init_db_quickscan():
    """Create quickscan and compliance-bestuur tables."""
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()

    c.execute('''CREATE TABLE IF NOT EXISTS quickscan_results (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        scan_type TEXT NOT NULL,
        company_name TEXT,
        responses TEXT NOT NULL,
        score INTEGER DEFAULT 0,
        max_score INTEGER DEFAULT 100,
        rag TEXT DEFAULT 'green',
        recommendations TEXT,
        created_at TEXT DEFAULT CURRENT_TIMESTAMP
    )''')

    c.execute('''CREATE TABLE IF NOT EXISTS compliance_deadlines (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        category TEXT NOT NULL,
        title TEXT NOT NULL,
        description TEXT,
        due_date TEXT NOT NULL,
        frequency TEXT DEFAULT 'jaarlijks',
        owner TEXT,
        status TEXT DEFAULT 'open',
        last_completed TEXT,
        created_at TEXT DEFAULT CURRENT_TIMESTAMP
    )''')

    c.execute('''CREATE TABLE IF NOT EXISTS generated_documents (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        doc_type TEXT NOT NULL,
        title TEXT NOT NULL,
        content TEXT,
        company_name TEXT,
        metadata TEXT,
        created_at TEXT DEFAULT CURRENT_TIMESTAMP
    )''')

    # Seed deadlines if empty
    cnt = c.execute('SELECT COUNT(*) FROM compliance_deadlines').fetchone()[0]
    if cnt == 0:
        deadlines = [
            ('BRZO', 'Veiligheidsrapport actualisatie', 'BRZO 2015 art. 9 — heractualisatie na wijzigingen', '2026-06-01', '5-jaarlijks'),
            ('BRZO', 'Extern noodplan oefening', 'BRZO 2015 art. 12 — jaarlijkse oefening', '2026-09-01', 'jaarlijks'),
            ('BRZO', 'MIR rapportage', 'Meldplicht incidenten gevaarlijke stoffen — direct', '2026-12-31', 'incidenteel'),
            ('Arbo', 'RI&E actualisatie', 'Arbowet art. 5 — periodieke herbeoordeling', '2026-07-01', 'jaarlijks'),
            ('Arbo', 'BHV oefening', 'Arbobesluit — minimaal 2x per jaar', '2026-06-15', 'halfjaarlijks'),
            ('Arbo', 'Preventiemedewerker overleg', 'Arbowet art. 13 — kwartaaloverleg', '2026-07-01', 'kwartaal'),
            ('ISO 45001', 'Interne audit', 'ISO 45001 §9.2 — jaarlijkse interne audit', '2026-10-01', 'jaarlijks'),
            ('ISO 14001', 'Management review', 'ISO 14001 §9.3 — jaarlijkse review', '2026-11-01', 'jaarlijks'),
            ('Milieu', 'Emissierapportage', 'Omgevingswet — jaarlijkse emissierapportage', '2026-03-31', 'jaarlijks'),
            ('PGS', 'PGS compliance check', 'PGS-richtlijnen actualisatie', '2026-08-01', 'jaarlijks'),
            ('Seveso', 'ARIE-notificatie actualisatie', 'ARIE-richtlijn — actualisatie bij wijzigingen', '2026-06-01', 'bij wijziging'),
            ('REACH/CLP', 'SDS actualisatie', 'REACH art. 31 — actualisatie bij nieuwe info', '2026-12-31', 'bij wijziging'),
            ('Omgevingswet', 'Vergunning actualisatie', 'Omgevingswet — herziening bij activiteitenwijziging', '2026-09-01', 'bij wijziging'),
        ]
        for d in deadlines:
            c.execute('INSERT INTO compliance_deadlines (category, title, description, due_date, frequency) VALUES (?,?,?,?,?)', d)

    conn.commit()
    conn.close()


# ─── Scan Definitions ──────────────────────────────────────────────────────

BRZO_QUESTIONS = [
    {"id": "q1", "text": "Is de inrichting BRZO-plichtig (klasse 1 t/m 6)?", "cat": "Classificatie", "weight": 10},
    {"id": "q2", "text": "Is het veiligheidsrapport (VR) aanwezig en actueel?", "cat": "Veiligheidsrapport", "weight": 10},
    {"id": "q3", "text": "Is de MAPP (Major Accident Prevention Policy) vastgesteld?", "cat": "MAPP", "weight": 8},
    {"id": "q4", "text": "Is het VBS (Veiligheidsbeheerssysteem) geïmplementeerd?", "cat": "VBS", "weight": 10},
    {"id": "q5", "text": "Is het intern noodplan opgesteld en geoefend?", "cat": "Noodplan", "weight": 8},
    {"id": "q6", "text": "Is het extern noodplan afgestemd met overheid?", "cat": "Noodplan", "weight": 8},
    {"id": "q7", "text": "Zijn VKA (veiligheidskritische apparatuur) gedefinieerd en gekeurd?", "cat": "VKA", "weight": 8},
    {"id": "q8", "text": "Is er een MoC (Management of Change) procedure?", "cat": "MoC", "weight": 6},
    {"id": "q9", "text": "Is de MIR-meldprocedure bekend en getest?", "cat": "MIR", "weight": 8},
    {"id": "q10", "text": "Worden BRZO-oefeningen periodiek uitgevoerd?", "cat": "Oefeningen", "weight": 8},
    {"id": "q11", "text": "Is de ARIE-notificatie gedaan?", "cat": "ARIE", "weight": 8},
    {"id": "q12", "text": "Is er een competentiebeheerssysteem voor veiligheidspersoneel?", "cat": "Competentie", "weight": 4},
    {"id": "q13", "text": "Zijn risicoanalyses (HAZOP/LOPA) uitgevoerd voor kritische installaties?", "cat": "Risicoanalyse", "weight": 8},
    {"id": "q14", "text": "Is er een inspectie-readiness procedure voor ILT/OD?", "cat": "Inspectie", "weight": 4},
]

SEVESO_QUESTIONS = [
    {"id": "sq1", "text": "Worden er stoffen opgeslagen/handled die op Annex I van Seveso III staan?", "cat": "Classificatie", "weight": 10},
    {"id": "sq2", "text": "Zijn de drempelwaarden voor Part 1 (categorieën) berekend?", "cat": "Drempelwaarden", "weight": 10},
    {"id": "sq3", "text": "Zijn de drempelwaarden voor Part 2 (benoemde stoffen) berekend?", "cat": "Drempelwaarden", "weight": 10},
    {"id": "sq4", "text": "Is de Seveso-classificatie (lower/upper tier) bepaald?", "cat": "Classificatie", "weight": 10},
    {"id": "sq5", "text": "Is de agglomeratie-regel (sommatie) toegepast bij meerdere stoffen?", "cat": "Agglomeratie", "weight": 8},
    {"id": "sq6", "text": "Is de QRA (kwantitatieve risicoberekening) uitgevoerd?", "cat": "QRA", "weight": 8},
    {"id": "sq7", "text": "Voldoet de locatie aan Bevi-vereisten (VR-contour, 10⁻⁶ grens)?", "cat": "Bevi", "weight": 8},
    {"id": "sq8", "text": "Is het voorlichtingsplicht (art. 14 Seveso III) nagekomen?", "cat": "Voorlichting", "weight": 6},
    {"id": "sq9", "text": "Is er een landinrichtingsplan (PRORAIL/gemeente) afstemming?", "cat": "Ruimtelijke ordening", "weight": 5},
    {"id": "sq10", "text": "Is de notificatie bij bevoegd gezag gedaan?", "cat": "Notificatie", "weight": 10},
]

ARBO_QUESTIONS = [
    {"id": "aq1", "text": "Is er een actuele RI&E (Risico-Inventarisatie & Evaluatie)?", "cat": "RI&E", "weight": 10},
    {"id": "aq2", "text": "Is er een preventiemedewerker (PMW) aangesteld?", "cat": "Organisatie", "weight": 8},
    {"id": "aq3", "text": "Is de BHV (Bedrijfshulpverlening) georganiseerd?", "cat": "BHV", "weight": 8},
    {"id": "aq4", "text": "Is er een bedrijfshulpverleningsplan?", "cat": "BHV", "weight": 6},
    {"id": "aq5", "text": "Worden periodiek arbocuratieve controles uitgevoerd?", "cat": "Controles", "weight": 6},
    {"id": "aq6", "text": "Zijn PSA (Persoonlijke Slachtofferhulp) middelen aanwezig?", "cat": "Middelen", "weight": 4},
    {"id": "aq7", "text": "Is er een geluid- en trillingsbeleid?", "cat": "Fysieke belasting", "weight": 5},
    {"id": "aq8", "text": "Is er een beleid voor psychosociale arbeidsbelasting (PSA)?", "cat": "PSA", "weight": 5},
    {"id": "aq9", "text": "Zijn arbeidsplaatsen voorzien van voldoende verlichting/ventilatie?", "cat": "Arbeidsomstandigheden", "weight": 4},
    {"id": "aq10", "text": "Is er een ongevallenregister bijgehouden?", "cat": "Registratie", "weight": 6},
    {"id": "aq11", "text": "Is er een asbestinventarisatie uitgevoerd (indien van toepassing)?", "cat": "Asbest", "weight": 4},
    {"id": "aq12", "text": "Is er een machinerichtlijn compliance check gedaan?", "cat": "Machines", "weight": 4},
]

MIR_QUESTIONS = [
    {"id": "mq1", "text": "Is men bekend met de MIR-meldplicht (art. 15 BRZO 2015)?", "cat": "Meldplicht", "weight": 10},
    {"id": "mq2", "text": "Is men bekend met de ARIE-meldplicht (Richtlijn 2012/18/EU)?", "cat": "ARIE", "weight": 10},
    {"id": "mq3", "text": "Is er een protocol voor melding aan ILT (Inspectie Leefomgeving en Transport)?", "cat": "ILT", "weight": 8},
    {"id": "mq4", "text": "Is er een protocol voor melding aan Inspectie SZW?", "cat": "SZW", "weight": 8},
    {"id": "mq5", "text": "Is er een protocol voor melding aan RIVM (nationaal毒encentrum)?", "cat": "RIVM", "weight": 6},
    {"id": "mq6", "text": "Zijn de 24-uurs en 72-uurs termijnen gedocumenteerd?", "cat": "Termijnen", "weight": 10},
    {"id": "mq7", "text": "Is er een incidentclassificatiesysteem (bijv. ECCS)?", "cat": "Classificatie", "weight": 6},
    {"id": "mq8", "text": "Worden bijna-ongevallen (near misses) geregistreerd en geanalyseerd?", "cat": "Near Miss", "weight": 6},
    {"id": "mq9", "text": "Is er een onderzoeksprotocol (SCO/SOT/EWIRA)?", "cat": "Onderzoek", "weight": 6},
    {"id": "mq10", "text": "Worden lessen geleerd gecommuniceerd naar betrokkenen?", "cat": "Lessons Learned", "weight": 4},
]


def calc_rag(score_pct):
    if score_pct >= 80:
        return 'green'
    elif score_pct >= 50:
        return 'amber'
    return 'red'


# ─── Routes ────────────────────────────────────────────────────────────────

def register_quickscan_routes(flask_app, page_func, BASE_PATH="/hseq-dashboard"):
    """Register all quickscan & compliance-bestuur routes."""

    # ─── 3.1 Compliance Bestuur Dashboard ─────────────────────────────
    @flask_app.route(BASE_PATH + '/compliance-bestuur')
    def compliance_bestuur_page():
        conn = get_db()

        # RAG matrix data
        categories = ['BRZO', 'Seveso', 'Arbo', 'Milieu', 'PGS', 'REACH/CLP', 'Omgevingswet']
        rag_data = {}
        for cat in categories:
            # Count from compliance_items
            try:
                total = conn.execute("SELECT COUNT(*) FROM compliance_items WHERE category LIKE ?", (f'%{cat}%',)).fetchone()[0]
                compliant = conn.execute("SELECT COUNT(*) FROM compliance_items WHERE category LIKE ? AND status='compliant'", (f'%{cat}%',)).fetchone()[0]
            except:
                total = 0
                compliant = 0
            if total > 0:
                pct = round(compliant / total * 100)
            else:
                pct = 50  # default
            rag_data[cat] = {'total': total, 'compliant': compliant, 'pct': pct, 'rag': calc_rag(pct)}

        # Readiness scores (from enriched scraped items)
        readiness_data = []
        try:
            for row in conn.execute('''
                SELECT category, COUNT(*) as cnt,
                       AVG(compliance_impact_score) as avg_score,
                       COUNT(CASE WHEN compliance_impact_score >= 4 THEN 1 END) as high_impact
                FROM scraped_items
                WHERE compliance_impact_score IS NOT NULL AND dismissed = 0
                GROUP BY category
                ORDER BY avg_score DESC
            ''').fetchall():
                readiness_data.append({
                    'category': row[0] or 'Overig',
                    'items': row[1],
                    'avg_score': round(row[2], 1) if row[2] else 0,
                    'high_impact': row[3]
                })
        except Exception as e:
            pass

        # Compliance actions (auto-generated from intelligence enrichment)
        compliance_actions = []
        try:
            for row in conn.execute('''
                SELECT id, source_skill, action_type, title, description, category,
                       priority, status, due_date, compliance_impact_score, legal_risk_level,
                       obligation_ref, created_date
                FROM compliance_actions
                WHERE status = 'open'
                ORDER BY
                    CASE priority WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END,
                    compliance_impact_score DESC NULLS LAST
                LIMIT 20
            ''').fetchall():
                compliance_actions.append({
                    'id': row[0], 'source_skill': row[1], 'action_type': row[2],
                    'title': row[3], 'description': row[4], 'category': row[5],
                    'priority': row[6], 'status': row[7], 'due_date': row[8],
                    'impact_score': row[9], 'legal_risk': row[10],
                    'obligation': row[11], 'created': row[12]
                })
        except Exception as e:
            pass

        # Deadlines with linked compliance_items
        deadlines = []
        try:
            for row in conn.execute('SELECT id, category, title, description, due_date, frequency, owner, status, last_completed FROM compliance_deadlines ORDER BY due_date ASC').fetchall():
                deadline_id = row[0]
                # Get linked compliance items
                linked_items = []
                for ci_row in conn.execute('''
                    SELECT id, requirement, status, article_ref
                    FROM compliance_items
                    WHERE deadline_id = ?
                    ORDER BY status
                ''', (deadline_id,)).fetchall():
                    linked_items.append({
                        'id': ci_row[0], 'requirement': ci_row[1],
                        'status': ci_row[2], 'article_ref': ci_row[3]
                    })
                # Get linked compliance_actions
                linked_actions = []
                for ca_row in conn.execute('''
                    SELECT id, title, priority, source_skill
                    FROM compliance_actions
                    WHERE deadline_id = ? AND status = 'open'
                    LIMIT 5
                ''', (deadline_id,)).fetchall():
                    linked_actions.append({
                        'id': ca_row[0], 'title': ca_row[1],
                        'priority': ca_row[2], 'skill': ca_row[3]
                    })
                deadlines.append({
                    'id': row[0], 'category': row[1], 'title': row[2], 'description': row[3],
                    'due_date': row[4], 'frequency': row[5], 'owner': row[6], 'status': row[7], 'last_completed': row[8],
                    'linked_items': linked_items,
                    'linked_actions': linked_actions
                })
        except:
            pass

        # Recent legislation changes from scraped items
        changes = []
        try:
            for row in conn.execute("SELECT id, title, source, scraped_at FROM scraped_items ORDER BY scraped_at DESC LIMIT 15").fetchall():
                changes.append({'id': row[0], 'title': row[1], 'source': row[2], 'date': row[3]})
        except:
            pass

        # Stats
        total_items = sum(v['total'] for v in rag_data.values())
        total_compliant = sum(v['compliant'] for v in rag_data.values())
        overall_pct = round(total_compliant / total_items * 100) if total_items > 0 else 0
        open_actions = 0
        try:
            open_actions = conn.execute("SELECT COUNT(*) FROM compliance_items WHERE status IN ('open','overdue')").fetchone()[0]
        except:
            pass

        body = '''
<div class="stats-grid" style="margin-bottom:20px">
  <div class="stat-card" style="border-left:4px solid #2B8A3E">
    <div class="value" style="color:#2B8A3E">{{overall_pct}}%</div>
    <div class="label">Overall Compliant</div>
  </div>
  <div class="stat-card">
    <div class="value">{{total_items}}</div>
    <div class="label">Totaal Eisen</div>
  </div>
  <div class="stat-card" style="border-left:4px solid #E03131">
    <div class="value" style="color:#E03131">{{open_actions}}</div>
    <div class="label">Open Acties</div>
  </div>
  <div class="stat-card" style="border-left:4px solid #4263EB">
    <div class="value">{{deadlines|length}}</div>
    <div class="label">Deadlines</div>
  </div>
</div>

<!-- RAG Matrix -->
<div class="card" style="margin-bottom:16px">
  <h2>🔴🟡🟢 RAG Compliance Matrix</h2>
  <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-top:16px">
    {% for cat, data in rag_data.items() %}
    <div style="border-radius:8px;padding:16px;background:#f8f9fa;border-left:4px solid {{'#2B8A3E' if data.rag=='green' else '#F59F00' if data.rag=='amber' else '#E03131'}}">
      <div style="font-weight:700;font-size:14px;margin-bottom:4px">{{cat}}</div>
      <div style="font-size:28px;font-weight:700;color:{{'#2B8A3E' if data.rag=='green' else '#F59F00' if data.rag=='amber' else '#E03131'}}">{{data.pct}}%</div>
      <div style="font-size:11px;color:#868E96">{{data.compliant}}/{{data.total}} compliant</div>
      <div style="margin-top:8px;height:6px;background:#E9ECEF;border-radius:3px;overflow:hidden">
        <div style="height:100%;width:{{data.pct}}%;background:{{'#2B8A3E' if data.rag=='green' else '#F59F00' if data.rag=='amber' else '#E03131'}};border-radius:3px"></div>
      </div>
    </div>
    {% endfor %}
  </div>
</div>

<!-- Deadlines -->
<div class="card" style="margin-bottom:16px">
  <h2>📅 Deadline Tracker <span style="font-size:11px;color:#868E96;font-weight:400">(gekoppeld aan compliance eisen + intelligence acties)</span></h2>
  <div style="overflow-x:auto;margin-top:12px">
    <table style="width:100%;font-size:12px;border-collapse:collapse">
      <thead><tr style="background:#f8f9fa;text-align:left">
        <th style="padding:8px">Categorie</th><th>Deadline</th><th>Titel</th><th>Gekoppelde Eisen</th><th>Intel. Acties</th><th>Frekwentie</th><th>Eigenaar</th><th>Status</th><th>Actie</th>
      </tr></thead>
      <tbody>
      {% for dl in deadlines %}
      <tr style="border-bottom:1px solid #eee">
        <td style="padding:8px"><span style="background:#E9ECEF;padding:2px 8px;border-radius:10px;font-size:11px">{{dl.category}}</span></td>
        <td style="padding:8px;font-weight:600">{{dl.due_date}}</td>
        <td style="padding:8px"><strong>{{dl.title}}</strong>{% if dl.description %}<br><span style="font-size:10px;color:#868E96">{{dl.description}}</span>{% endif %}</td>
        <td style="padding:8px">
          {% if dl.linked_items %}
          {% for li in dl.linked_items %}
          <div style="margin-bottom:2px">
            <span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:{{'#2B8A3E' if li.status=='compliant' else '#F59F00' if li.status=='in_progress' else '#E03131'}};margin-right:4px"></span>
            <span style="font-size:10px">{{li.requirement[:50]}}</span>
          </div>
          {% endfor %}
          {% else %}<span style="color:#868E96;font-size:10px">—</span>{% endif %}
        </td>
        <td style="padding:8px">
          {% if dl.linked_actions %}
          {% for la in dl.linked_actions %}
          <div style="margin-bottom:2px">
            <span style="font-size:10px;background:{{'#E03131' if la.priority=='high' else '#F59F00'}};color:#fff;padding:1px 4px;border-radius:4px">{{la.skill[:4]}}</span>
            <span style="font-size:10px">{{la.title[:40]}}</span>
          </div>
          {% endfor %}
          {% else %}<span style="color:#868E96;font-size:10px">—</span>{% endif %}
        </td>
        <td style="padding:8px;font-size:11px">{{dl.frequency}}</td>
        <td style="padding:8px">{{dl.owner or '—'}}</td>
        <td style="padding:8px"><span style="background:{{'#2B8A3E' if dl.status=='completed' else '#F59F00' if dl.status=='in_progress' else '#E03131'}};color:#fff;padding:2px 8px;border-radius:10px;font-size:11px">{{dl.status}}</span></td>
        <td style="padding:8px">
          {% if dl.status == 'completed' %}
            <button onclick="reopenDeadline({{dl.id}})" class="btn btn-sm btn-outline">↩️ Open</button>
          {% else %}
            <button onclick="markInProgress({{dl.id}})" class="btn btn-sm btn-outline">⏳ Start</button>
          {% endif %}
        </td>
      </tr>
      {% endfor %}
      </tbody>
    </table>
  </div>
</div>

<!-- Wijzigingen Feed -->
<div class="card">
  <h2>📰 Recente Wetgevingwijzigingen</h2>
  {% if changes %}
  <div style="margin-top:12px">
    {% for ch in changes %}
    <div style="padding:8px;border-bottom:1px solid #f0f0f0;display:flex;justify-content:space-between;align-items:center">
      <div><strong style="font-size:13px">{{ch.title[:80]}}</strong><br><span style="font-size:11px;color:#868E96">{{ch.source}}</span></div>
      <span style="font-size:11px;color:#868E96">{{ch.date[:10] if ch.date else ''}}</span>
    </div>
    {% endfor %}
  </div>
  {% else %}
  <div style="padding:20px;text-align:center;color:#868E96">Geen recente wijzigingen beschikbaar. Start de scraper om items te verzamelen.</div>
  {% endif %}
</div>

<!-- Intelligence Compliance Impact -->
{% if readiness_data %}
<div class="card" style="margin-top:16px">
  <h2>🧠 Intelligence Impact Scores</h2>
  <p style="font-size:11px;color:#868E96;margin-top:4px">Gemiddelde compliance-impact per categorie (uit Intelligence Feed enrichment)</p>
  <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-top:12px">
    {% for rd in readiness_data %}
    <div style="border-radius:8px;padding:12px;background:#f8f9fa;border-left:4px solid {{'#E03131' if rd.avg_score >= 4 else '#F59F00' if rd.avg_score >= 3 else '#4263EB' if rd.avg_score >= 2 else '#868E96'}}">
      <div style="font-weight:700;font-size:12px">{{rd.category}}</div>
      <div style="font-size:24px;font-weight:700;color:{{'#E03131' if rd.avg_score >= 4 else '#F59F00' if rd.avg_score >= 3 else '#4263EB'}}">{{rd.avg_score}}/5</div>
      <div style="font-size:10px;color:#868E96">{{rd.items}} items · {{rd.high_impact}} hoog impact</div>
    </div>
    {% endfor %}
  </div>
</div>
{% endif %}

<!-- Auto-Generated Compliance Actions -->
{% if compliance_actions %}
<div class="card" style="margin-top:16px">
  <h2>⚡ Acties uit Intelligence Scan</h2>
  <p style="font-size:11px;color:#868E96;margin-top:4px">Automatisch gegenereerd door Compliance-Readiness, Legal en Complianceclaw skills</p>
  <div style="overflow-x:auto;margin-top:12px">
    <table style="width:100%;font-size:12px;border-collapse:collapse">
      <thead><tr style="background:#f8f9fa;text-align:left">
        <th style="padding:8px">Actie</th>
        <th style="padding:8px">Skill</th>
        <th style="padding:8px">Categorie</th>
        <th style="padding:8px">Impact</th>
        <th style="padding:8px">Legal</th>
        <th style="padding:8px">Deadline</th>
        <th style="padding:8px">Prioriteit</th>
        <th style="padding:8px">Actie</th>
      </tr></thead>
      <tbody>
      {% for ca in compliance_actions %}
      <tr style="border-bottom:1px solid #eee">
        <td style="padding:8px"><strong>{{ca.title[:60]}}</strong>{% if ca.description %}<br><span style="font-size:10px;color:#868E96">{{ca.description[:100]}}</span>{% endif %}</td>
        <td style="padding:8px"><span style="background:#E9ECEF;padding:2px 6px;border-radius:6px;font-size:10px">{{ca.source_skill}}</span></td>
        <td style="padding:8px">{{ca.category or '—'}}</td>
        <td style="padding:8px;font-weight:700;color:{{'#E03131' if ca.impact_score and ca.impact_score >= 4 else '#F59F00' if ca.impact_score and ca.impact_score >= 3 else '#2B8A3E'}}">{{ca.impact_score or '—'}}/5</td>
        <td style="padding:8px"><span style="background:{{'#E03131' if ca.legal_risk in ('HOOG','KRITIEK') else '#F59F00' if ca.legal_risk == 'MEDIUM' else '#2B8A3E'}};color:#fff;padding:2px 6px;border-radius:6px;font-size:10px">{{ca.legal_risk or '—'}}</span></td>
        <td style="padding:8px">{{ca.due_date[:10] if ca.due_date else '—'}}</td>
        <td style="padding:8px"><span style="background:{{'#E03131' if ca.priority == 'high' else '#F59F00'}};color:#fff;padding:2px 6px;border-radius:6px;font-size:10px">{{ca.priority}}</span></td>
        <td style="padding:8px"><button onclick="closeAction({{ca.id}})" class="btn btn-sm btn-outline" style="font-size:10px">✅</button></td>
      </tr>
      {% endfor %}
      </tbody>
    </table>
  </div>
</div>
{% endif %}

<script>
var BASE = '{{BASE_PATH}}';
function markInProgress(id) {
  fetch(BASE+'/api/compliance/deadlines/'+id+'/start', {method:'POST'})
    .then(r=>r.json()).then(()=>location.reload());
}
function completeDeadline(id) {
  fetch(BASE+'/api/compliance/deadlines/'+id+'/complete', {method:'POST'})
    .then(r=>r.json()).then(()=>location.reload());
}
function reopenDeadline(id) {
  fetch(BASE+'/api/compliance/deadlines/'+id+'/reopen', {method:'POST'})
    .then(r=>r.json()).then(()=>location.reload());
}
function closeAction(id) {
  fetch(BASE+'/api/compliance/actions/'+id+'/close', {method:'POST'})
    .then(r=>r.json()).then(()=>location.reload());
}
</script>
'''
        return page_func(body,
            page_title='Compliance Bestuur',
            active='compliance-bestuur',
            rag_data=rag_data,
            deadlines=deadlines,
            changes=changes,
            readiness_data=readiness_data,
            compliance_actions=compliance_actions,
            overall_pct=overall_pct,
            total_items=total_items,
            open_actions=open_actions,
            BASE_PATH='')

    # ─── API: Start Progress Deadline (VERBETERING) ────────────────────
    @flask_app.route(BASE_PATH + '/api/compliance/deadlines/<int:dl_id>/start', methods=['POST'])
    def start_deadline(dl_id):
        conn = sqlite3.connect(DB_PATH)
        conn.execute('UPDATE compliance_deadlines SET status=?, last_started=? WHERE id=?',
            ('in_progress', date.today().isoformat(), dl_id))
        conn.commit(); conn.close()
        return jsonify({'ok': True})

    # ─── API: Complete Deadline ───────────────────────────────────────
    @flask_app.route(BASE_PATH + '/api/compliance/deadlines/<int:dl_id>/complete', methods=['POST'])
    def complete_deadline(dl_id):
        conn = sqlite3.connect(DB_PATH)
        conn.execute('UPDATE compliance_deadlines SET status=?, last_completed=? WHERE id=?',
            ('completed', date.today().isoformat(), dl_id))
        conn.commit(); conn.close()
        return jsonify({'ok': True})

    # ─── API: Reopen Deadline (VERBETERING) ─────────────────────────────
    @flask_app.route(BASE_PATH + '/api/compliance/deadlines/<int:dl_id>/reopen', methods=['POST'])
    def reopen_deadline(dl_id):
        conn = sqlite3.connect(DB_PATH)
        conn.execute('UPDATE compliance_deadlines SET status=?, last_completed=NULL WHERE id=?',
            ('open', dl_id))
        conn.commit(); conn.close()
        return jsonify({'ok': True})

    # ─── API: Close Compliance Action ──────────────────────────────────
    @flask_app.route(BASE_PATH + '/api/compliance/actions/<int:action_id>/close', methods=['POST'])
    def close_compliance_action(action_id):
        conn = sqlite3.connect(DB_PATH)
        conn.execute('UPDATE compliance_actions SET status=?, closed_date=? WHERE id=?',
            ('closed', date.today().isoformat(), action_id))
        conn.commit(); conn.close()
        return jsonify({'ok': True})

    # ─── API: Compliance Actions List ──────────────────────────────────
    @flask_app.route(BASE_PATH + '/api/compliance/actions')
    def api_compliance_actions():
        status = request.args.get('status', 'open')
        skill = request.args.get('skill', '')
        conn = sqlite3.connect(DB_PATH)
        query = 'SELECT * FROM compliance_actions WHERE status = ?'
        params = [status]
        if skill:
            query += ' AND source_skill = ?'
            params.append(skill)
        query += ' ORDER BY compliance_impact_score DESC NULLS LAST, created_date DESC LIMIT 50'
        rows = conn.execute(query, params).fetchall()
        cols = [d[0] for d in conn.execute('SELECT * FROM compliance_actions LIMIT 0').description]
        result = [dict(zip(cols, row)) for row in rows]
        conn.close()
        return jsonify({'actions': result, 'count': len(result)})

    # ─── API: Compliance Overview ──────────────────────────────────────
    @flask_app.route(BASE_PATH + '/api/compliance/overview')
    def api_compliance_overview():
        conn = get_db()
        categories = ['BRZO', 'Seveso', 'Arbo', 'Milieu', 'PGS', 'REACH/CLP', 'Omgevingswet']
        result = {}
        for cat in categories:
            try:
                total = conn.execute("SELECT COUNT(*) FROM compliance_items WHERE category LIKE ?", (f'%{cat}%',)).fetchone()[0]
                compliant = conn.execute("SELECT COUNT(*) FROM compliance_items WHERE category LIKE ? AND status='compliant'", (f'%{cat}%',)).fetchone()[0]
            except:
                total, compliant = 0, 0
            pct = round(compliant/total*100) if total > 0 else 0
            result[cat] = {'total': total, 'compliant': compliant, 'pct': pct, 'rag': calc_rag(pct)}
        return jsonify(result)

    @flask_app.route(BASE_PATH + '/api/compliance/scan', methods=['POST'])
    def api_compliance_scan_save():
        d = request.get_json()
        conn = sqlite3.connect(DB_PATH)
        conn.execute('INSERT INTO quickscan_results (scan_type, company_name, responses, score, max_score, rag, recommendations) VALUES (?,?,?,?,?,?,?)',
            (d.get('scan_type',''), d.get('company_name',''), json.dumps(d.get('responses',{})),
             d.get('score',0), d.get('max_score',100), d.get('rag','green'), json.dumps(d.get('recommendations',[]))))
        conn.commit(); conn.close()
        return jsonify({'ok': True})

    @flask_app.route(BASE_PATH + '/api/compliance/deadlines')
    def api_compliance_deadlines():
        conn = sqlite3.connect(DB_PATH)
        rows = conn.execute('SELECT * FROM compliance_deadlines ORDER BY due_date ASC').fetchall()
        conn.close()
        return jsonify([{'id':r[0],'category':r[1],'title':r[2],'description':r[3],'due_date':r[4],'frequency':r[5],'owner':r[6],'status':r[7]} for r in rows])

    @flask_app.route(BASE_PATH + '/api/compliance/changes')
    def api_compliance_changes():
        conn = get_db()
        try:
            rows = conn.execute("SELECT id, title, source, scraped_at FROM scraped_items ORDER BY scraped_at DESC LIMIT 30").fetchall()
            return jsonify([{'id':r[0],'title':r[1],'source':r[2],'date':r[3]} for r in rows])
        except:
            return jsonify([])

    # ─── 3.2 Quick-Scan Pages ─────────────────────────────────────────

    @flask_app.route(BASE_PATH + '/quickscan')
    def quickscan_overview():
        body = '''
<div class="card">
  <h2>🔍 Quick-Scan Tools</h2>
  <p style="color:#868E96;margin:8px 0 16px">Interactieve self-assessment tools voor HSEQ compliance.</p>
  <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px">
    <a href="{{BASE_PATH}}/quickscan/brzo" class="card" style="text-decoration:none;display:block;padding:20px;border-left:4px solid #E03131">
      <div style="font-size:24px;margin-bottom:8px">🏭</div>
      <div style="font-weight:700;font-size:16px;color:#003366">BRZO Quick Scan</div>
      <div style="font-size:12px;color:#868E96;margin-top:4px">Is het bedrijf BRZO-compliant? 14 vragen over veiligheidsrapport, noodplan, MIR, VKA en meer.</div>
    </a>
    <a href="{{BASE_PATH}}/quickscan/seveso" class="card" style="text-decoration:none;display:block;padding:20px;border-left:4px solid #F76707">
      <div style="font-size:24px;margin-bottom:8px">⚠️</div>
      <div style="font-weight:700;font-size:16px;color:#003366">Seveso Self-Assessment</div>
      <div style="font-size:12px;color:#868E96;margin-top:4px">Classificatiecheck: drempelwaarden, agglomeratie, Bevi en QRA.</div>
    </a>
    <a href="{{BASE_PATH}}/quickscan/arbo" class="card" style="text-decoration:none;display:block;padding:20px;border-left:4px solid #4263EB">
      <div style="font-size:24px;margin-bottom:8px">👷</div>
      <div style="font-weight:700;font-size:16px;color:#003366">Arbo Checklist</div>
      <div style="font-size:12px;color:#868E96;margin-top:4px">Arbowetgeving compliance: RI&E, PMW, BHV, PSA en meer.</div>
    </a>
    <a href="{{BASE_PATH}}/quickscan/mir" class="card" style="text-decoration:none;display:block;padding:20px;border-left:4px solid #7048E8">
      <div style="font-size:24px;margin-bottom:8px">🚨</div>
      <div style="font-weight:700;font-size:16px;color:#003366">MIR Checklist</div>
      <div style="font-size:12px;color:#868E96;margin-top:4px">Meldplicht check: welke incidenten moeten gemeld worden en bij welke instantie?</div>
    </a>
  </div>
</div>

<!-- Recent Scans -->
<div class="card" style="margin-top:16px">
  <h2>📊 Recente Scans</h2>
  <div id="recent-scans" style="margin-top:12px"><div style="text-align:center;padding:20px;color:#868E96">Scans worden hier weergegeven...</div></div>
</div>

<script>
var BASE='{{BASE_PATH}}';
fetch(BASE+'/api/quickscan/history').then(r=>r.json()).then(data=>{
  if(!data.length) return;
  document.getElementById('recent-scans').innerHTML='<table style="width:100%;font-size:12px;border-collapse:collapse"><thead><tr style="background:#f8f9fa"><th style="padding:8px;text-align:left">Type</th><th>Bedrijf</th><th>Score</th><th>RAG</th><th>Datum</th></tr></thead><tbody>'+
    data.map(s=>'<tr style="border-bottom:1px solid #eee"><td style="padding:8px">'+s.scan_type+'</td><td style="padding:8px">'+(s.company_name||'-')+'</td><td style="padding:8px;font-weight:600">'+s.score+'/'+s.max_score+'</td><td style="padding:8px"><span style="background:'+({green:'#2B8A3E',amber:'#F59F00',red:'#E03131'}[s.rag])+';color:#fff;padding:2px 8px;border-radius:10px;font-size:11px">'+s.rag.toUpperCase()+'</span></td><td style="padding:8px;font-size:11px;color:#868E96">'+s.created_at+'</td></tr>').join('')+
    '</tbody></table>';
});
</script>
'''
        return page_func(body, page_title='Quick-Scan Tools', active='quickscan')

    def _render_scan_page_raw(scan_type, title, emoji, questions, color):
        """Render full page, bypassing Jinja for the JS-heavy scan content."""
        q_json = json.dumps(questions)
        base = "/hseq-dashboard"
        # Build body HTML (safe, no Jinja conflicts)
        body_html = '''<div class="card">
  <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px">
    <div>
      <a href="''' + base + '''/quickscan" class="btn btn-outline btn-sm">&larr; Terug</a>
      <h2 style="display:inline;margin-left:12px">''' + emoji + ' ' + title + '''</h2>
    </div>
    <div id="scan-result-badge" style="display:none"></div>
  </div>
  <div style="background:#f8f9fa;border-radius:8px;padding:16px;margin-bottom:16px">
    <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
      <div><label style="display:block;font-size:12px;font-weight:600;margin-bottom:4px">Bedrijfsnaam</label>
        <input id="company" placeholder="Bedrijfsnaam..." style="width:100%;padding:8px;border:1px solid #dee2e6;border-radius:6px"></div>
      <div><label style="display:block;font-size:12px;font-weight:600;margin-bottom:4px">Beoordelaar</label>
        <input id="assessor" placeholder="Naam..." style="width:100%;padding:8px;border:1px solid #dee2e6;border-radius:6px"></div>
    </div>
  </div>
  <div id="questions-container"></div>
  <div style="margin-top:20px;display:flex;gap:8px">
    <button onclick="submitScan()" class="btn btn-primary" style="flex:1;padding:12px;font-size:14px">Bereken Score</button>
    <button onclick="resetScan()" class="btn btn-outline">Reset</button>
  </div>
  <div id="scan-result" style="display:none;margin-top:20px"></div>
</div>'''
        # Use page_func for layout (Jinja-safe body), inject JS separately
        full_html = page_func(body_html, page_title=title, active='quickscan')
        # Append JS as a raw script block before </body>
        js = _build_scan_js(q_json, base, scan_type)
        full_html = full_html.replace('</body>', js + '\n</body>')
        return full_html

    def _build_scan_js(q_json, base, scan_type):
        return '<script>\nvar QUESTIONS = ' + q_json + ';\nvar BASE = "' + base + '";\nvar scanType = "' + scan_type + '";\nfunction renderQuestions() {\n  var html = "";\n  QUESTIONS.forEach(function(q, i) {\n    html += \'<div style="padding:12px;border-bottom:1px solid #f0f0f0"><div style="display:flex;justify-content:space-between;align-items:start"><div style="flex:1"><span style="font-size:11px;color:#868E96">Vraag \'+(i+1)+\'\\u2022 \'+q.cat+\'</span><div style="font-weight:500;font-size:13px;margin-top:2px">\'+q.text+\'</div></div><div style="display:flex;gap:4px;margin-left:12px"><label style="display:flex;align-items:center;gap:4px;font-size:12px;padding:4px 10px;background:#D3F9D8;border-radius:4px;cursor:pointer;border:2px solid transparent" id="lbl-\'+q.id+\'-1"><input type="radio" name="\'+q.id+\'" value="1" style="display:none"> Ja</label><label style="display:flex;align-items:center;gap:4px;font-size:12px;padding:4px 10px;background:#FFF3BF;border-radius:4px;cursor:pointer;border:2px solid transparent" id="lbl-\'+q.id+\'-0.5"><input type="radio" name="\'+q.id+\'" value="0.5" style="display:none"> Gedeeltelijk</label><label style="display:flex;align-items:center;gap:4px;font-size:12px;padding:4px 10px;background:#FFE3E3;border-radius:4px;cursor:pointer;border:2px solid transparent" id="lbl-\'+q.id+\'-0"><input type="radio" name="\'+q.id+\'" value="0" style="display:none"> Nee</label></div></div></div>\';\n  });\n  document.getElementById("questions-container").innerHTML = html;\n  document.querySelectorAll("input[type=radio]").forEach(function(inp) { inp.addEventListener("change", function() { var name=this.name;var val=this.value;["1","0.5","0"].forEach(function(v){var lbl=document.getElementById("lbl-"+name+"-"+v);if(lbl)lbl.style.borderColor=v===val?"#003366":"transparent";});});});\n}\nfunction submitScan(){var maxScore=0,score=0,responses={},allAnswered=true;QUESTIONS.forEach(function(q){maxScore+=q.weight;var sel=document.querySelector("input[name=\\""+q.id+"\\"]:checked");if(!sel){allAnswered=false;return;}var val=parseFloat(sel.value);score+=q.weight*val;responses[q.id]={question:q.text,answer:val,weight:q.weight};});if(!allAnswered){alert("Beantwoord alle vragen.");return;}var pct=Math.round(score/maxScore*100);var rag=pct>=80?"green":pct>=50?"amber":"red";var ragLabel=rag==="green"?"COMPLIANT":rag==="amber"?"DEELS COMPLIANT":"NIET COMPLIANT";var ragColor=rag==="green"?"#2B8A3E":rag==="amber"?"#F59F00":"#E03131";var recs=[];QUESTIONS.forEach(function(q){var r=responses[q.id];if(r&&r.answer<1)recs.push({text:q.text,priority:r.answer===0?"Hoog":"Medium",cat:q.cat});});document.getElementById("scan-result-badge").style.display="block";document.getElementById("scan-result-badge").innerHTML="<span style=background:"+ragColor+";color:#fff;padding:6px 16px;border-radius:6px;font-weight:700>"+ragLabel+" — "+pct+"%</span>";var h="<div style=border-radius:8px;padding:20px;background:"+ragColor+"10;border:2px solid "+ragColor+"><h3 style=color:"+ragColor+";margin:0 0 12px>Score: "+score.toFixed(1)+" / "+maxScore+" ("+pct+"%)</h3>";if(recs.length>0){h+="<h4>Aanbevelingen</h4><table style=width:100%;font-size:12px;border-collapse:collapse><thead><tr style=background:#f8f9fa><th style=padding:6px;text-align:left>Vraag</th><th>Cat</th><th>Prioriteit</th></tr></thead><tbody>";recs.forEach(function(r){h+="<tr style=border-bottom:1px solid #eee><td style=padding:6px>"+r.text+"</td><td style=padding:6px>"+r.cat+"</td><td style=padding:6px><span style=background:"+(r.priority==="Hoog"?"#E03131":"#F59F00")+";color:#fff;padding:2px 8px;border-radius:10px;font-size:11px>"+r.priority+"</span></td></tr>";});h+="</tbody></table>";}else{h+="<p style=color:#2B8A3E;font-weight:600>Volledig compliant.</p>";}h+="</div><div style=margin-top:12px><button onclick=saveScan() class=btn btn-primary>Opslaan</button></div>";document.getElementById("scan-result").innerHTML=h;document.getElementById("scan-result").style.display="block";window._scanData={scan_type:scanType,company_name:document.getElementById("company").value,responses:responses,score:Math.round(score),max_score:maxScore,rag:rag,recommendations:recs};}\nfunction saveScan(){if(!window._scanData)return;fetch(BASE+"/api/compliance/scan",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(window._scanData)}).then(function(r){return r.json()}).then(function(d){if(d.ok)alert("Scan opgeslagen!");});}\nfunction resetScan(){document.querySelectorAll("input[type=radio]").forEach(function(i){i.checked=false;});document.querySelectorAll("[id^=lbl-]").forEach(function(l){l.style.borderColor="transparent";});document.getElementById("scan-result").style.display="none";document.getElementById("scan-result-badge").style.display="none";}\nrenderQuestions();\n</script>'
    from flask import Response as FlaskResponse
    @flask_app.route(BASE_PATH + '/quickscan/brzo')
    def quickscan_brzo():
        body = _render_scan_page_raw('BRZO', 'BRZO Quick Scan', '🏭', BRZO_QUESTIONS, '#E03131')
        return FlaskResponse(body, mimetype='text/html')

    @flask_app.route(BASE_PATH + '/quickscan/seveso')
    def quickscan_seveso():
        body = _render_scan_page_raw('Seveso', 'Seveso Self-Assessment', '⚠️', SEVESO_QUESTIONS, '#F76707')
        return FlaskResponse(body, mimetype='text/html')

    @flask_app.route(BASE_PATH + '/quickscan/arbo')
    def quickscan_arbo():
        body = _render_scan_page_raw('Arbo', 'Arbo Checklist', '👷', ARBO_QUESTIONS, '#4263EB')
        return FlaskResponse(body, mimetype='text/html')

    @flask_app.route(BASE_PATH + '/quickscan/mir')
    def quickscan_mir():
        body = _render_scan_page_raw('MIR', 'MIR Checklist', '🚨', MIR_QUESTIONS, '#7048E8')
        return FlaskResponse(body, mimetype='text/html')

    # ─── Quick-Scan API endpoints ──────────────────────────────────────
    @flask_app.route(BASE_PATH + '/api/quickscan/brzo', methods=['POST'])
    def api_quickscan_brzo():
        return api_compliance_scan_save.__wrapped__(request) if hasattr(api_compliance_scan_save, '__wrapped__') else jsonify({'ok': True})

    @flask_app.route(BASE_PATH + '/api/quickscan/seveso', methods=['POST'])
    def api_quickscan_seveso():
        return jsonify({'ok': True})

    @flask_app.route(BASE_PATH + '/api/quickscan/arbo', methods=['POST'])
    def api_quickscan_arbo():
        return jsonify({'ok': True})

    @flask_app.route(BASE_PATH + '/api/quickscan/mir', methods=['POST'])
    def api_quickscan_mir():
        return jsonify({'ok': True})

    @flask_app.route(BASE_PATH + '/api/quickscan/history')
    def api_quickscan_history():
        conn = sqlite3.connect(DB_PATH)
        rows = conn.execute('SELECT id, scan_type, company_name, score, max_score, rag, created_at FROM quickscan_results ORDER BY created_at DESC LIMIT 20').fetchall()
        conn.close()
        return jsonify([{'id':r[0],'scan_type':r[1],'company_name':r[2],'score':r[3],'max_score':r[4],'rag':r[5],'created_at':r[6][:16] if r[6] else ''} for r in rows])

    # ─── 3.3 Document Generators ──────────────────────────────────────

    @flask_app.route(BASE_PATH + '/api/generate/rie', methods=['POST'])
    def api_generate_rie():
        d = request.get_json()
        conn = sqlite3.connect(DB_PATH)
        conn.execute('INSERT INTO generated_documents (doc_type, title, content, company_name, metadata) VALUES (?,?,?,?,?)',
            ('rie', d.get('title','RI&E'), d.get('content',''), d.get('company_name',''), json.dumps(d.get('metadata',{}))))
        conn.commit(); conn.close()
        return jsonify({'ok': True, 'message': 'RI&E template gegenereerd'})

    @flask_app.route(BASE_PATH + '/api/generate/tra', methods=['POST'])
    def api_generate_tra():
        d = request.get_json()
        conn = sqlite3.connect(DB_PATH)
        conn.execute('INSERT INTO generated_documents (doc_type, title, content, company_name, metadata) VALUES (?,?,?,?,?)',
            ('tra', d.get('title','TRA'), d.get('content',''), d.get('company_name',''), json.dumps(d.get('metadata',{}))))
        conn.commit(); conn.close()
        return jsonify({'ok': True, 'message': 'TRA gegenereerd'})

    @flask_app.route(BASE_PATH + '/api/generate/veiligheidsplan', methods=['POST'])
    def api_generate_veiligheidsplan():
        d = request.get_json()
        conn = sqlite3.connect(DB_PATH)
        conn.execute('INSERT INTO generated_documents (doc_type, title, content, company_name, metadata) VALUES (?,?,?,?,?)',
            ('veiligheidsplan', d.get('title','Veiligheidsplan'), d.get('content',''), d.get('company_name',''), json.dumps(d.get('metadata',{}))))
        conn.commit(); conn.close()
        return jsonify({'ok': True, 'message': 'Veiligheidsplan gegenereerd'})
