# ============================================================
# MODULE: KAM Management Dienst Transformatie — FASE 5
# HSEQ Intelligence Dashboard
# ISO 9001/14001/45001 Self-Assessment, Gap Analyse,
# Audit Programma, Management Review, Continu Verbetering
# ============================================================

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

BASE_PATH = ''

# ─── ISO Clause Data ──────────────────────────────────────────────────────

ISO_CLAUSES = {
    'ISO 9001:2015': {
        'name': 'Quality Management System',
        'clauses': [
            ('4', 'Context of the Organization'),
            ('4.1', 'Understanding the organization and its context'),
            ('4.2', 'Understanding the needs and expectations of interested parties'),
            ('4.3', 'Determining the scope of the QMS'),
            ('4.4', 'Quality management system and its processes'),
            ('5', 'Leadership'),
            ('5.1', 'Leadership and commitment'),
            ('5.2', 'Policy'),
            ('5.3', 'Organizational roles, responsibilities and authorities'),
            ('6', 'Planning'),
            ('6.1', 'Actions to address risks and opportunities'),
            ('6.2', 'Quality objectives and planning to achieve them'),
            ('6.3', 'Planning of changes'),
            ('7', 'Support'),
            ('7.1', 'Resources'),
            ('7.2', 'Competence'),
            ('7.3', 'Awareness'),
            ('7.4', 'Communication'),
            ('7.5', 'Documented information'),
            ('8', 'Operation'),
            ('8.1', 'Operational planning and control'),
            ('8.2', 'Requirements for products and services'),
            ('8.3', 'Design and development of products and services'),
            ('8.4', 'Control of externally provided processes, products, and services'),
            ('8.5', 'Production and service provision'),
            ('8.6', 'Release of products and services'),
            ('8.7', 'Control of nonconforming outputs'),
            ('9', 'Performance evaluation'),
            ('9.1', 'Monitoring, measurement, analysis and evaluation'),
            ('9.2', 'Internal audit'),
            ('9.3', 'Management review'),
            ('10', 'Improvement'),
            ('10.1', 'General'),
            ('10.2', 'Nonconformity and corrective action'),
            ('10.3', 'Continual improvement'),
        ]
    },
    'ISO 14001:2015': {
        'name': 'Environmental Management System',
        'clauses': [
            ('4', 'Context of the Organization'),
            ('4.1', 'Understanding the organization and its context'),
            ('4.2', 'Understanding the needs and expectations of interested parties'),
            ('4.3', 'Determining the scope of the EMS'),
            ('4.4', 'Environmental management system'),
            ('5', 'Leadership'),
            ('5.1', 'Leadership and commitment'),
            ('5.2', 'Environmental policy'),
            ('5.3', 'Organizational roles, responsibilities and authorities'),
            ('6', 'Planning'),
            ('6.1', 'Actions to address risks and opportunities'),
            ('6.1.2', 'Environmental aspects'),
            ('6.1.3', 'Compliance obligations'),
            ('6.1.4', 'Planning action'),
            ('6.2', 'Environmental objectives and planning to achieve them'),
            ('7', 'Support'),
            ('7.1', 'Resources'),
            ('7.2', 'Competence'),
            ('7.3', 'Awareness'),
            ('7.4', 'Communication'),
            ('7.5', 'Documented information'),
            ('8', 'Operation'),
            ('8.1', 'Operational planning and control'),
            ('8.2', 'Emergency preparedness and response'),
            ('9', 'Performance evaluation'),
            ('9.1', 'Monitoring, measurement, analysis and evaluation'),
            ('9.2', 'Internal audit'),
            ('9.3', 'Management review'),
            ('10', 'Improvement'),
            ('10.1', 'General'),
            ('10.2', 'Nonconformity and corrective action'),
            ('10.3', 'Continual improvement'),
        ]
    },
    'ISO 45001:2018': {
        'name': 'Occupational Health & Safety Management System',
        'clauses': [
            ('4', 'Context of the Organization'),
            ('4.1', 'Understanding the organization and its context'),
            ('4.2', 'Understanding the needs and expectations of workers'),
            ('4.3', 'Determining the scope of the OH&S management system'),
            ('4.4', 'OH&S management system'),
            ('5', 'Leadership and worker participation'),
            ('5.1', 'Leadership and commitment'),
            ('5.2', 'OH&S policy'),
            ('5.3', 'Organizational roles, responsibilities and authorities'),
            ('5.4', 'Worker participation and consultation'),
            ('6', 'Planning'),
            ('6.1', 'Actions to address risks and opportunities'),
            ('6.1.2', 'Hazard identification and assessment of risks'),
            ('6.1.3', 'Assessment of OH&S opportunities'),
            ('6.1.4', 'Determination of legal requirements and other requirements'),
            ('6.2', 'OH&S objectives and planning to achieve them'),
            ('6.3', 'Planning for change management'),
            ('6.4', 'Planning for temporary and permanent changes'),
            ('7', 'Support'),
            ('7.1', 'Resources'),
            ('7.2', 'Competence'),
            ('7.3', 'Awareness'),
            ('7.4', 'Communication'),
            ('7.4.1', 'Internal communication'),
            ('7.4.2', 'External communication'),
            ('7.5', 'Documented information'),
            ('8', 'Operation'),
            ('8.1', 'Operational planning and control'),
            ('8.1.1', 'Elimination of hazards and reduction of OH&S risks'),
            ('8.1.2', 'Hierarchy of controls'),
            ('8.1.3', 'Management of change'),
            ('8.1.4', 'Procurement'),
            ('8.1.5', 'Contractors'),
            ('8.1.6', 'Emergency preparedness and response'),
            ('8.2', 'Incident, nonconformity and corrective action'),
            ('9', 'Performance evaluation'),
            ('9.1', 'Monitoring, measurement, analysis and evaluation'),
            ('9.2', 'Evaluation of compliance'),
            ('9.3', 'Internal audit'),
            ('9.4', 'Management review'),
            ('10', 'Improvement'),
            ('10.1', 'General'),
            ('10.2', 'Incident, nonconformity and corrective action'),
            ('10.3', 'Continual improvement'),
        ]
    }
}

# ─── Dashboard Template ──────────────────────────────────────────────────

KAM_DASHBOARD_TEMPLATE = '''
<style>
.kam-wrap .tabs{display:flex;gap:4px;margin-bottom:24px;border-bottom:1px solid var(--border);padding-bottom:0}
.kam-wrap .tab{padding:10px 20px;cursor:pointer;border-radius:8px 8px 0 0;font-size:14px;font-weight:500;color:var(--text-secondary);transition:all .2s}
.kam-wrap .tab:hover{color:var(--text);background:var(--card-bg)}
.kam-wrap .tab.active{color:var(--primary);background:var(--card-bg);border-bottom:2px solid var(--primary)}
.kam-wrap .panel{display:none;background:var(--card-bg);border-radius:0 8px 8px 8px;padding:24px;border:1px solid var(--border)}
.kam-wrap .panel.active{display:block}
.kam-wrap .grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px;margin-bottom:24px}
.kam-wrap .card{background:var(--bg);border-radius:8px;padding:20px;border:1px solid var(--border)}
.kam-wrap .card h3{font-size:14px;color:var(--text-secondary);margin-bottom:8px;text-transform:uppercase;letter-spacing:.5px}
.kam-wrap .card .value{font-size:32px;font-weight:700;color:var(--primary)}
.kam-wrap .card .sub{font-size:12px;color:var(--text-secondary);margin-top:4px}
.kam-wrap .btn{display:inline-flex;align-items:center;gap:6px;padding:8px 16px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;border:none;transition:all .2s}
.kam-wrap .btn-primary{background:var(--primary);color:#fff}.kam-wrap .btn-primary:hover{opacity:.85}
.kam-wrap .btn-secondary{background:var(--border);color:var(--text)}.kam-wrap .btn-secondary:hover{opacity:.8}
.kam-wrap .btn-danger{background:#dc2626;color:#fff}.kam-wrap .btn-danger:hover{background:#b91c1c}
.kam-wrap .btn-success{background:#059669;color:#fff}.kam-wrap .btn-success:hover{background:#047857}
.kam-wrap select,.kam-wrap input,.kam-wrap textarea{background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:8px 12px;font-size:14px;width:100%}
.kam-wrap select:focus,.kam-wrap input:focus,.kam-wrap textarea:focus{outline:none;border-color:var(--primary)}
.kam-wrap table{width:100%;border-collapse:collapse;font-size:13px}
.kam-wrap th{text-align:left;padding:10px 12px;background:var(--bg);color:var(--text-secondary);font-weight:600;border-bottom:1px solid var(--border);position:sticky;top:0}
.kam-wrap td{padding:10px 12px;border-bottom:1px solid var(--border);color:var(--text)}
.kam-wrap tr:hover{background:var(--table-hover,var(--bg))}
.kam-wrap .badge-status{padding:3px 10px;border-radius:10px;font-size:11px;font-weight:600}
.kam-wrap .badge-green{background:#05966920;color:#10b981}.kam-wrap .badge-red{background:#dc262620;color:#ef4444}
.kam-wrap .badge-yellow{background:#d9770620;color:#f59e0b}.kam-wrap .badge-blue{background:#3b82f620;color:#60a5fa}
.kam-wrap .badge-gray{background:#47556920;color:#94a3b8}
.kam-wrap .form-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}
.kam-wrap .form-group{margin-bottom:16px}
.kam-wrap .form-group label{display:block;font-size:13px;color:var(--text-secondary);margin-bottom:6px;font-weight:500}
.kam-wrap .progress-bar{height:8px;background:var(--border);border-radius:4px;overflow:hidden}
.kam-wrap .progress-fill{height:100%;border-radius:4px;transition:width .3s}
.kam-wrap .modal-overlay{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.6);z-index:1000;justify-content:center;align-items:center}
.kam-wrap .modal-overlay.active{display:flex}
.kam-wrap .modal{background:var(--card-bg);border-radius:12px;padding:24px;width:90%;max-width:600px;max-height:80vh;overflow-y:auto;border:1px solid var(--border)}
.kam-wrap .modal h2{margin-bottom:16px;color:var(--text)}
.kam-wrap .actions{display:flex;gap:8px;flex-wrap:wrap}
.kam-wrap .score-circle{width:60px;height:60px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:18px}
.kam-wrap h2{color:var(--text)}
</style>
<div style="max-width:1400px;margin:0 auto;" class="kam-wrap">
<div class="container">
  <div class="tabs">
    <div class="tab active" data-tab="dashboard">📊 Dashboard</div>
    <div class="tab" data-tab="selfassessment">📋 Self-Assessment</div>
    <div class="tab" data-tab="gapanalyse">🔍 Gap Analyse</div>
    <div class="tab" data-tab="auditprogramma">📅 Audit Programma</div>
    <div class="tab" data-tab="mgmtreview">📑 Management Review</div>
    <div class="tab" data-tab="verbetering">♻️ Continu Verbetering</div>
  </div>

  <!-- DASHBOARD -->
  <div class="panel active" id="panel-dashboard">
    <div class="grid" id="dash-cards"></div>
    <div style="display:grid;grid-template-columns:1fr 1fr;gap:16px">
      <div class="card"><h3>Recente Self-Assessments</h3><div id="dash-recent-sa" style="margin-top:12px"></div></div>
      <div class="card"><h3>Open Gaps (Top Risico)</h3><div id="dash-recent-gaps" style="margin-top:12px"></div></div>
    </div>
  </div>

  <!-- SELF-ASSESSMENT -->
  <div class="panel" id="panel-selfassessment">
    <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:20px">
      <h2>ISO Self-Assessment</h2>
      <div class="actions">
        <select id="sa-iso-select" style="width:200px" onchange="loadAssessment()">
          <option value="">— Selecteer ISO Standaard —</option>
          <option value="ISO 9001:2015">ISO 9001:2015 — Quality</option>
          <option value="ISO 14001:2015">ISO 14001:2015 — Environmental</option>
          <option value="ISO 45001:2018">ISO 45001:2018 — OH&S</option>
        </select>
        <button class="btn btn-primary" onclick="newAssessment()">+ Nieuwe Assessment</button>
      </div>
    </div>
    <div id="sa-content"></div>
  </div>

  <!-- GAP ANALYSE -->
  <div class="panel" id="panel-gapanalyse">
    <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:20px">
      <h2>Gap Analyse</h2>
      <div class="actions">
        <button class="btn btn-primary" onclick="generateGapAnalysis()">🔍 Genereer Gap Analyse</button>
        <button class="btn btn-secondary" onclick="exportGapReport()">📥 Export Rapport</button>
      </div>
    </div>
    <div id="gap-content"></div>
  </div>

  <!-- AUDIT PROGRAMMA -->
  <div class="panel" id="panel-auditprogramma">
    <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:20px">
      <h2>Audit Programma Generator</h2>
      <div class="actions">
        <button class="btn btn-primary" onclick="showAuditModal()">+ Nieuw Audit Plan</button>
      </div>
    </div>
    <div id="audit-content"></div>
  </div>

  <!-- MANAGEMENT REVIEW -->
  <div class="panel" id="panel-mgmtreview">
    <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:20px">
      <h2>Management Review</h2>
      <div class="actions">
        <button class="btn btn-primary" onclick="showMgmtReviewModal()">+ Nieuwe Review</button>
      </div>
    </div>
    <div id="mgmt-content"></div>
  </div>

  <!-- CONTINU VERBETERING -->
  <div class="panel" id="panel-verbetering">
    <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:20px">
      <h2>Continu Verbetering (PDCA)</h2>
      <div class="actions">
        <button class="btn btn-primary" onclick="showImprovementModal()">+ Nieuwe Verbeteractie</button>
      </div>
    </div>
    <div id="improve-content"></div>
  </div>
</div>

<!-- MODAL -->
<div class="modal-overlay" id="modal-overlay">
  <div class="modal" id="modal-body"></div>
</div>

<script>
const API = '__BP__/api/kam';
const BASE = '__BP__';


// Tabs
document.querySelectorAll('.tab').forEach(t => {
  t.addEventListener('click', () => {
    document.querySelectorAll('.tab').forEach(x => x.classList.remove('active'));
    document.querySelectorAll('.panel').forEach(x => x.classList.remove('active'));
    t.classList.add('active');
    document.getElementById('panel-' + t.dataset.tab).classList.add('active');
    loadTab(t.dataset.tab);
  });
});

function loadTab(tab) {
  if (tab === 'dashboard') loadDashboard();
  else if (tab === 'selfassessment') loadAssessment();
  else if (tab === 'gapanalyse') loadGaps();
  else if (tab === 'auditprogramma') loadAudits();
  else if (tab === 'mgmtreview') loadMgmtReviews();
  else if (tab === 'verbetering') loadImprovements();
}

async function api(url, opts = {}) {
  try {
    const r = await fetch(API + url, opts);
    return await r.json();
  } catch(e) { console.error(e); return {error: e.message}; }
}

function scoreColor(s) {
  if (s >= 80) return '#10b981'; if (s >= 60) return '#f59e0b'; if (s >= 40) return '#f97316'; return '#ef4444';
}
function statusBadge(s) {
  const m = {'compliant':'badge-green','partial':'badge-yellow','non_compliant':'badge-red','not_assessed':'badge-gray',
    'planned':'badge-blue','in_progress':'badge-yellow','completed':'badge-green','cancelled':'badge-gray',
    'open':'badge-red','closed':'badge-green','in_review':'badge-yellow','overdue':'badge-red',
    'high':'badge-red','medium':'badge-yellow','low':'badge-green','critical':'badge-red'};
  return `<span class="badge-status ${m[s]||'badge-gray'}">${s.replace('_',' ')}</span>`;
}
function closeModal() { document.getElementById('modal-overlay').classList.remove('active'); }

// ─── DASHBOARD ───
async function loadDashboard() {
  const d = await api('/dashboard');
  if (d.error) return;
  document.getElementById('dash-cards').innerHTML = `
    <div class="card"><h3>Totale Assessments</h3><div class="value">${d.total_assessments||0}</div><div class="sub">ISO 9001/14001/45001</div></div>
    <div class="card"><h3>Gemiddelde Score</h3><div class="value" style="color:${scoreColor(d.avg_score||0)}">${d.avg_score?d.avg_score+'%':'-'}</div><div class="sub">Over alle assessments</div></div>
    <div class="card"><h3>Open Gaps</h3><div class="value">${d.open_gaps||0}</div><div class="sub">${d.critical_gaps||0} kritiek</div></div>
    <div class="card"><h3>Audit Programma</h3><div class="value">${d.total_audits||0}</div><div class="sub">${d.audits_completed||0} afgerond</div></div>
    <div class="card"><h3>PDCA Acties</h3><div class="value">${d.total_improvements||0}</div><div class="sub">${d.improvements_active||0} actief</div></div>
    <div class="card"><h3>Management Reviews</h3><div class="value">${d.total_reviews||0}</div><div class="sub">${d.reviews_completed||0} afgerond</div></div>`;
  const sa = await api('/assessments?limit=5');
  document.getElementById('dash-recent-sa').innerHTML = sa.length ? `<table><tr><th>Datum</th><th>ISO</th><th>Score</th></tr>${sa.map(a=>`<tr><td>${a.created_at?.split(' ')[0]||'-'}</td><td>${a.iso_standard}</td><td style="color:${scoreColor(a.total_score)}">${a.total_score}%</td></tr>`).join('')}</table>` : '<p style="color:var(--text-secondary)">Geen assessments</p>';
  const gaps = await api('/gaps?status=open&limit=5');
  document.getElementById('dash-recent-gaps').innerHTML = gaps.length ? `<table><tr><th>Clause</th><th>Risico</th><th>ISO</th></tr>${gaps.map(g=>`<tr><td>${g.clause_ref}</td><td>${statusBadge(g.risk_level)}</td><td>${g.iso_standard}</td></tr>`).join('')}</table>` : '<p style="color:var(--text-secondary)">Geen open gaps</p>';
}

// ─── SELF-ASSESSMENT ───
let currentAssessment = null;
async function loadAssessment() {
  const iso = document.getElementById('sa-iso-select').value;
  const content = document.getElementById('sa-content');
  if (!iso) { content.innerHTML = '<p style="color:var(--text-secondary)">Selecteer een ISO standaard om te beginnen.</p>'; return; }
  const list = await api('/assessments?iso_standard=' + encodeURIComponent(iso) + '&limit=10');
  let html = '<table><tr><th>Datum</th><th>Score</th><th>Status</th><th>Acties</th></tr>';
  if (list.length) {
    list.forEach(a => { html += `<tr><td>${a.created_at?.split(' ')[0]}</td><td style="color:${scoreColor(a.total_score)};font-weight:700">${a.total_score}%</td><td>${statusBadge(a.status)}</td><td><button class="btn btn-secondary" style="padding:4px 10px;font-size:12px" onclick="viewAssessment(${a.id})">Bekijk</button></td></tr>`; });
  } else { html += '<tr><td colspan="4" style="color:var(--text-secondary)">Geen assessments voor deze standaard</td></tr>'; }
  html += '</table>';
  content.innerHTML = html;
}

async function newAssessment() {
  const iso = document.getElementById('sa-iso-select').value;
  if (!iso) { alert('Selecteer eerst een ISO standaard.'); return; }
  const d = await api('/clauses?iso_standard=' + encodeURIComponent(iso));
  if (d.error) return;
  let rows = '';
  d.forEach((c,i) => { rows += `<tr><td>${c.clause_ref}</td><td>${c.clause_title}</td><td><select id="sa-s-${i}"><option value="5">5 — Volledig compliant</option><option value="4">4 — Grotendeels compliant</option><option value="3">3 — Gedeeltelijk compliant</option><option value="2">2 — Weinig compliant</option><option value="1">1 — Niet compliant</option><option value="0">0 — Niet geïmplementeerd</option></select></td><td><input id="sa-e-${i}" placeholder="Bewijslast / opmerking"></td><td id="sa-g-${i}">-</td></tr>`; });
  document.getElementById('modal-body').innerHTML = `<h2>Nieuwe Assessment — ${iso}</h2>
    <div class="form-group"><label>Assessor</label><input id="sa-assessor" value="HSEQ Manager"></div>
    <div class="form-group"><label>Scope / Afdeling</label><input id="sa-scope" placeholder="bv. Hele organisatie"></div>
    <div style="max-height:50vh;overflow-y:auto"><table><tr><th>Clause</th><th>Omschrijving</th><th>Score</th><th>Bewijslast</th><th>Gap</th></tr>${rows}</table></div>
    <div style="margin-top:16px;display:flex;gap:8px"><button class="btn btn-primary" onclick="saveAssessment('${iso}',${d.length})">💾 Opslaan</button><button class="btn btn-secondary" onclick="closeModal()">Annuleer</button></div>`;
  document.getElementById('modal-overlay').classList.add('active');
}

async function saveAssessment(iso, count) {
  const clauses = [];
  for (let i = 0; i < count; i++) {
    const score = parseInt(document.getElementById('sa-s-'+i).value);
    const evidence = document.getElementById('sa-e-'+i).value;
    const gap = score < 4 ? (score < 2 ? 'critical' : 'medium') : (score < 5 ? 'low' : 'none');
    document.getElementById('sa-g-'+i).innerHTML = statusBadge(gap === 'none' ? 'compliant' : gap);
    clauses.push({score, evidence, gap});
  }
  // fetch clauses from API for refs
  const clauseData = await api('/clauses?iso_standard=' + encodeURIComponent(iso));
  const items = clauseData.map((c,i) => ({clause_ref: c.clause_ref, clause_title: c.clause_title, ...clauses[i]}));
  const result = await api('/assessments', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({
    iso_standard: iso, assessor: document.getElementById('sa-assessor').value,
    scope: document.getElementById('sa-scope').value, clauses: items
  })});
  if (result.id) { alert('Assessment opgeslagen! Score: ' + result.total_score + '%'); closeModal(); loadAssessment(); }
  else alert('Fout: ' + (result.error||'onbekend'));
}

async function viewAssessment(id) {
  const d = await api('/assessments/' + id);
  if (d.error) return;
  const clauses = JSON.parse(d.clauses || '[]');
  let rows = clauses.map(c => `<tr><td>${c.clause_ref}</td><td>${c.clause_title}</td><td style="color:${scoreColor(c.score*20)};font-weight:700">${c.score}/5</td><td>${c.evidence||'-'}</td><td>${statusBadge(c.gap==='none'?'compliant':c.gap)}</td></tr>`).join('');
  document.getElementById('modal-body').innerHTML = `<h2>Assessment — ${d.iso_standard}</h2>
    <p style="color:#94a3b8;margin-bottom:12px">Assessor: ${d.assessor} | Score: <strong style="color:${scoreColor(d.total_score)}">${d.total_score}%</strong> | ${d.created_at?.split(' ')[0]}</p>
    <div style="max-height:60vh;overflow-y:auto"><table><tr><th>Clause</th><th>Omschrijving</th><th>Score</th><th>Bewijslast</th><th>Gap</th></tr>${rows}</table></div>
    <div style="margin-top:16px"><button class="btn btn-secondary" onclick="closeModal()">Sluiten</button></div>`;
  document.getElementById('modal-overlay').classList.add('active');
}

// ─── GAP ANALYSE ───
async function loadGaps() {
  const gaps = await api('/gaps?limit=50');
  if (gaps.error) return;
  let html = `<table><tr><th>ISO</th><th>Clause</th><th>Omschrijving</th><th>Risico</th><th>Status</th><th>Acties</th></tr>`;
  gaps.forEach(g => { html += `<tr><td>${g.iso_standard}</td><td>${g.clause_ref}</td><td style="max-width:250px;overflow:hidden;text-overflow:ellipsis">${g.description||'-'}</td><td>${statusBadge(g.risk_level)}</td><td>${statusBadge(g.status)}</td><td><button class="btn btn-secondary" style="padding:4px 10px;font-size:12px" onclick="editGap(${g.id})">✏️</button></td></tr>`; });
  if (!gaps.length) html += '<tr><td colspan="6" style="color:var(--text-secondary)">Geen gaps gevonden. Voer eerst een self-assessment uit.</td></tr>';
  html += '</table>';
  document.getElementById('gap-content').innerHTML = html;
}

async function generateGapAnalysis() {
  const gaps = await api('/gaps/generate', {method:'POST'});
  if (gaps.generated !== undefined) { alert(`${gaps.generated} gaps gegenereerd, ${gaps.updated} geüpdatet.`); loadGaps(); }
  else alert('Fout: ' + (gaps.error||'onbekend'));
}

async function editGap(id) {
  const g = await api('/gaps/' + id);
  if (g.error) return;
  document.getElementById('modal-body').innerHTML = `<h2>Gap Bewerken — ${g.clause_ref}</h2>
    <div class="form-group"><label>Omschrijving</label><textarea id="gap-desc" rows="3">${g.description||''}</textarea></div>
    <div class="form-row"><div class="form-group"><label>Risico</label><select id="gap-risk"><option value="low" ${g.risk_level==='low'?'selected':''}>Low</option><option value="medium" ${g.risk_level==='medium'?'selected':''}>Medium</option><option value="high" ${g.risk_level==='high'?'selected':''}>High</option><option value="critical" ${g.risk_level==='critical'?'selected':''}>Critical</option></select></div><div class="form-group"><label>Status</label><select id="gap-status"><option value="open" ${g.status==='open'?'selected':''}>Open</option><option value="in_progress" ${g.status==='in_progress'?'selected':''}>In Progress</option><option value="closed" ${g.status==='closed'?'selected':''}>Closed</option></select></div></div>
    <div class="form-group"><label>Actieplan</label><textarea id="gap-action" rows="3">${g.action_plan||''}</textarea></div>
    <div style="margin-top:16px;display:flex;gap:8px"><button class="btn btn-primary" onclick="saveGap(${g.id})">💾 Opslaan</button><button class="btn btn-secondary" onclick="closeModal()">Annuleer</button></div>`;
  document.getElementById('modal-overlay').classList.add('active');
}

async function saveGap(id) {
  await api('/gaps/' + id, {method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify({
    description: document.getElementById('gap-desc').value,
    risk_level: document.getElementById('gap-risk').value,
    status: document.getElementById('gap-status').value,
    action_plan: document.getElementById('gap-action').value
  })});
  closeModal(); loadGaps();
}

function exportGapReport() {
  window.open(API + '/gaps/export', '_blank');
}

// ─── AUDIT PROGRAMMA ───
async function loadAudits() {
  const audits = await api('/audits?limit=50');
  if (audits.error) return;
  let html = `<table><tr><th>ISO</th><th>Type</th><th>Scope</th><th>Auditor</th><th>Gepland</th><th>Frequentie</th><th>Status</th><th>Acties</th></tr>`;
  audits.forEach(a => { html += `<tr><td>${a.iso_standard||'-'}</td><td>${a.audit_type}</td><td>${a.scope||'-'}</td><td>${a.auditor||'-'}</td><td>${a.scheduled_date||'-'}</td><td>${a.frequency||'-'}</td><td>${statusBadge(a.status)}</td><td><button class="btn btn-secondary" style="padding:4px 10px;font-size:12px" onclick="editAudit(${a.id})">✏️</button></td></tr>`; });
  if (!audits.length) html += '<tr><td colspan="8" style="color:var(--text-secondary)">Geen audits gepland.</td></tr>';
  html += '</table>';
  document.getElementById('audit-content').innerHTML = html;
}

function showAuditModal() {
  document.getElementById('modal-body').innerHTML = `<h2>Nieuw Audit Plan</h2>
    <div class="form-row"><div class="form-group"><label>ISO Standaard</label><select id="aud-iso"><option value="ISO 9001:2015">ISO 9001:2015</option><option value="ISO 14001:2015">ISO 14001:2015</option><option value="ISO 45001:2018">ISO 45001:2018</option><option value="Internal">Internal</option></select></div><div class="form-group"><label>Type</label><select id="aud-type"><option value="internal">Internal</option><option value="external">External</option><option value="supplier">Supplier</option><option value="certification">Certification</option></select></div></div>
    <div class="form-row"><div class="form-group"><label>Scope</label><input id="aud-scope" placeholder="bv. Productie afdeling"></div><div class="form-group"><label>Auditor</label><input id="aud-auditor" placeholder="Naam auditor"></div></div>
    <div class="form-row"><div class="form-group"><label>Geplande Datum</label><input id="aud-date" type="date"></div><div class="form-group"><label>Frequentie</label><select id="aud-freq"><option value="maandelijks">Maandelijks</option><option value="kwartaal">Kwartaal</option><option value="halfjaar">Halfjaar</option><option value="jaarlijks">Jaarlijks</option><option value="eenmalig">Eenmalig</option></select></div></div>
    <div class="form-group"><label>Opmerkingen</label><textarea id="aud-notes" rows="2"></textarea></div>
    <div style="margin-top:16px;display:flex;gap:8px"><button class="btn btn-primary" onclick="saveAudit()">💾 Opslaan</button><button class="btn btn-secondary" onclick="closeModal()">Annuleer</button></div>`;
  document.getElementById('modal-overlay').classList.add('active');
}

async function saveAudit() {
  await api('/audits', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({
    iso_standard: document.getElementById('aud-iso').value,
    audit_type: document.getElementById('aud-type').value,
    scope: document.getElementById('aud-scope').value,
    auditor: document.getElementById('aud-auditor').value,
    scheduled_date: document.getElementById('aud-date').value,
    frequency: document.getElementById('aud-freq').value,
    notes: document.getElementById('aud-notes').value
  })});
  closeModal(); loadAudits();
}

async function editAudit(id) {
  const a = await api('/audits/' + id);
  if (a.error) return;
  document.getElementById('modal-body').innerHTML = `<h2>Audit Bewerken</h2>
    <div class="form-row"><div class="form-group"><label>Status</label><select id="aud-st"><option value="planned" ${a.status==='planned'?'selected':''}>Gepland</option><option value="in_progress" ${a.status==='in_progress'?'selected':''}>Uitvoerend</option><option value="completed" ${a.status==='completed'?'selected':''}>Afgerond</option><option value="rejected" ${a.status==='rejected'?'selected':''}>Afgekeurd</option><option value="cancelled" ${a.status==='cancelled'?'selected':''}>Geannuleerd</option></select></div><div class="form-group"><label>Resultaat</label><textarea id="aud-result" rows="3">${a.result||''}</textarea></div></div>
    <div class="form-group"><label>Opmerkingen</label><textarea id="aud-notes" rows="2">${a.notes||''}</textarea></div>
    <div style="margin-top:16px;display:flex;gap:8px"><button class="btn btn-primary" onclick="updateAudit(${a.id})">💾 Opslaan</button><button class="btn btn-secondary" onclick="closeModal()">Annuleer</button></div>`;
  document.getElementById('modal-overlay').classList.add('active');
}

async function updateAudit(id) {
  await api('/audits/' + id, {method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify({
    status: document.getElementById('aud-st').value,
    result: document.getElementById('aud-result').value,
    notes: document.getElementById('aud-notes').value
  })});
  closeModal(); loadAudits();
}

// ─── MANAGEMENT REVIEW ───
async function loadMgmtReviews() {
  const reviews = await api('/reviews?limit=50');
  if (reviews.error) return;
  let html = `<table><tr><th>Datum</th><th>Type</th><th>Beslissingen</th><th>Status</th><th>Acties</th></tr>`;
  reviews.forEach(r => { html += `<tr><td>${r.review_date||r.created_at?.split(' ')[0]}</td><td>${r.review_type||'-'}</td><td style="max-width:300px;overflow:hidden;text-overflow:ellipsis">${r.decisions||'-'}</td><td>${statusBadge(r.status)}</td><td><button class="btn btn-secondary" style="padding:4px 10px;font-size:12px" onclick="editReview(${r.id})">✏️</button></td></tr>`; });
  if (!reviews.length) html += '<tr><td colspan="5" style="color:var(--text-secondary)">Geen reviews.</td></tr>';
  html += '</table>';
  document.getElementById('mgmt-content').innerHTML = html;
}

function showMgmtReviewModal() {
  document.getElementById('modal-body').innerHTML = `<h2>Nieuwe Management Review</h2>
    <div class="form-row"><div class="form-group"><label>Datum</label><input id="rv-date" type="date"></div><div class="form-group"><label>Type</label><select id="rv-type"><option value="periodiek">Periodiek</option><option value="ad_hoc">Ad Hoc</option><option value="pre_certificering">Pre-Certificering</option><option value="follow_up">Follow-Up</option></select></div></div>
    <div class="form-group"><label>KPI Samenvatting</label><textarea id="rv-kpi" rows="2" placeholder="Bv. TRIR: 0.8, Near-miss rapportage: +15%, etc."></textarea></div>
    <div class="form-group"><label>Input: Incidenten & Audit Resultaten</label><textarea id="rv-input" rows="3" placeholder="Overzicht incidenten, audit findings, klachten"></textarea></div>
    <div class="form-group"><label>Beslissingen & Acties</label><textarea id="rv-decisions" rows="3" placeholder="Directiebeslissingen en actiepunten"></textarea></div>
    <div class="form-group"><label>Vervolgdatum</label><input id="rv-followup" type="date"></div>
    <div style="margin-top:16px;display:flex;gap:8px"><button class="btn btn-primary" onclick="saveReview()">💾 Opslaan</button><button class="btn btn-secondary" onclick="closeModal()">Annuleer</button></div>`;
  document.getElementById('modal-overlay').classList.add('active');
}

async function saveReview() {
  await api('/reviews', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({
    review_date: document.getElementById('rv-date').value,
    review_type: document.getElementById('rv-type').value,
    kpi_summary: document.getElementById('rv-kpi').value,
    input_summary: document.getElementById('rv-input').value,
    decisions: document.getElementById('rv-decisions').value,
    followup_date: document.getElementById('rv-followup').value
  })});
  closeModal(); loadMgmtReviews();
}

async function editReview(id) {
  const r = await api('/reviews/' + id);
  if (r.error) return;
  document.getElementById('modal-body').innerHTML = `<h2>Management Review Bewerken</h2>
    <div class="form-row"><div class="form-group"><label>Status</label><select id="rv-st"><option value="planned" ${r.status==='planned'?'selected':''}>Gepland</option><option value="completed" ${r.status==='completed'?'selected':''}>Afgerond</option><option value="cancelled" ${r.status==='cancelled'?'selected':''}>Geannuleerd</option></select></div><div class="form-group"><label>Vervolgdatum</label><input id="rv-fu" type="date" value="${r.followup_date||''}"></div></div>
    <div class="form-group"><label>Notities</label><textarea id="rv-notes" rows="3">${r.notes||''}</textarea></div>
    <div style="margin-top:16px;display:flex;gap:8px"><button class="btn btn-primary" onclick="updateReview(${r.id})">💾 Opslaan</button><button class="btn btn-secondary" onclick="closeModal()">Annuleer</button></div>`;
  document.getElementById('modal-overlay').classList.add('active');
}

async function updateReview(id) {
  await api('/reviews/' + id, {method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify({
    status: document.getElementById('rv-st').value,
    followup_date: document.getElementById('rv-fu').value,
    notes: document.getElementById('rv-notes').value
  })});
  closeModal(); loadMgmtReviews();
}

// ─── CONTINU VERBETERING ───
async function loadImprovements() {
  const items = await api('/improvements?limit=50');
  if (items.error) return;
  let html = `<table><tr><th>PDCA</th><th>Omschrijving</th><th>ISO</th><th>Before</th><th>After</th><th>Status</th><th>Acties</th></tr>`;
  items.forEach(i => { html += `<tr><td><span class="badge-status badge-blue">${i.pdca_stage}</span></td><td style="max-width:250px;overflow:hidden;text-overflow:ellipsis">${i.title}</td><td>${i.iso_standard||'-'}</td><td>${i.metric_before||'-'}</td><td>${i.metric_after||'-'}</td><td>${statusBadge(i.status)}</td><td><button class="btn btn-secondary" style="padding:4px 10px;font-size:12px" onclick="editImprovement(${i.id})">✏️</button></td></tr>`; });
  if (!items.length) html += '<tr><td colspan="7" style="color:var(--text-secondary)">Geen verbeteracties.</td></tr>';
  html += '</table>';
  document.getElementById('improve-content').innerHTML = html;
}

function showImprovementModal() {
  document.getElementById('modal-body').innerHTML = `<h2>Nieuwe Verbeteractie (PDCA)</h2>
    <div class="form-row"><div class="form-group"><label>Titel</label><input id="imp-title" placeholder="Korte beschrijving"></div><div class="form-group"><label>ISO Standaard</label><select id="imp-iso"><option value="">— Geen —</option><option value="ISO 9001:2015">ISO 9001</option><option value="ISO 14001:2015">ISO 14001</option><option value="ISO 45001:2018">ISO 45001</option></select></div></div>
    <div class="form-group"><label>Omschrijving</label><textarea id="imp-desc" rows="2"></textarea></div>
    <div class="form-row"><div class="form-group"><label>PDCA Fase</label><select id="imp-pdca"><option value="plan">Plan</option><option value="do">Do</option><option value="check">Check</option><option value="act">Act</option></select></div><div class="form-group"><label>Prioriteit</label><select id="imp-prio"><option value="low">Low</option><option value="medium">Medium</option><option value="high">High</option></select></div></div>
    <div class="form-row"><div class="form-group"><label>Before Metric</label><input id="imp-before" placeholder="Bv. TRIR 1.2"></div><div class="form-group"><label>Target Metric</label><input id="imp-target" placeholder="Bv. TRIR 0.8"></div></div>
    <div class="form-group"><label>Verantwoordelijke</label><input id="imp-owner" placeholder="Naam"></div>
    <div style="margin-top:16px;display:flex;gap:8px"><button class="btn btn-primary" onclick="saveImprovement()">💾 Opslaan</button><button class="btn btn-secondary" onclick="closeModal()">Annuleer</button></div>`;
  document.getElementById('modal-overlay').classList.add('active');
}

async function saveImprovement() {
  await api('/improvements', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({
    title: document.getElementById('imp-title').value,
    iso_standard: document.getElementById('imp-iso').value,
    description: document.getElementById('imp-desc').value,
    pdca_stage: document.getElementById('imp-pdca').value,
    priority: document.getElementById('imp-prio').value,
    metric_before: document.getElementById('imp-before').value,
    metric_target: document.getElementById('imp-target').value,
    owner: document.getElementById('imp-owner').value
  })});
  closeModal(); loadImprovements();
}

async function editImprovement(id) {
  const i = await api('/improvements/' + id);
  if (i.error) return;
  document.getElementById('modal-body').innerHTML = `<h2>Verbeteractie Bewerken</h2>
    <div class="form-row"><div class="form-group"><label>PDCA Fase</label><select id="imp-pdca"><option value="plan" ${i.pdca_stage==='plan'?'selected':''}>Plan</option><option value="do" ${i.pdca_stage==='do'?'selected':''}>Do</option><option value="check" ${i.pdca_stage==='check'?'selected':''}>Check</option><option value="act" ${i.pdca_stage==='act'?'selected':''}>Act</option></select></div><div class="form-group"><label>Status</label><select id="imp-st"><option value="open" ${i.status==='open'?'selected':''}>Open</option><option value="in_progress" ${i.status==='in_progress'?'selected':''}>In Progress</option><option value="completed" ${i.status==='completed'?'selected':''}>Completed</option><option value="cancelled" ${i.status==='cancelled'?'selected':''}>Cancelled</option></select></div></div>
    <div class="form-row"><div class="form-group"><label>After Metric</label><input id="imp-after" value="${i.metric_after||''}" placeholder="Bv. TRIR 0.6"></div><div class="form-group"><label>Verantwoordelijke</label><input id="imp-owner" value="${i.owner||''}"></div></div>
    <div class="form-group"><label>Notities / Effectmeting</label><textarea id="imp-notes" rows="3">${i.notes||''}</textarea></div>
    <div style="margin-top:16px;display:flex;gap:8px"><button class="btn btn-primary" onclick="updateImprovement(${i.id})">💾 Opslaan</button><button class="btn btn-secondary" onclick="closeModal()">Annuleer</button></div>`;
  document.getElementById('modal-overlay').classList.add('active');
}

async function updateImprovement(id) {
  await api('/improvements/' + id, {method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify({
    pdca_stage: document.getElementById('imp-pdca').value,
    status: document.getElementById('imp-st').value,
    metric_after: document.getElementById('imp-after').value,
    owner: document.getElementById('imp-owner').value,
    notes: document.getElementById('imp-notes').value
  })});
  closeModal(); loadImprovements();
}

// Init
loadDashboard();

</script>'''


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

def init_kam_db():
    """Create KAM management tables."""
    try:
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()

        # Self-Assessments
        c.execute('''CREATE TABLE IF NOT EXISTS kam_assessments (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            iso_standard TEXT NOT NULL,
            assessor TEXT DEFAULT 'HSEQ Manager',
            scope TEXT,
            clauses TEXT NOT NULL,
            total_score INTEGER DEFAULT 0,
            status TEXT DEFAULT 'completed',
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )''')

        # Gap Analysis
        c.execute('''CREATE TABLE IF NOT EXISTS kam_gaps (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            iso_standard TEXT NOT NULL,
            assessment_id INTEGER,
            clause_ref TEXT NOT NULL,
            clause_title TEXT,
            description TEXT,
            risk_level TEXT DEFAULT 'medium',
            status TEXT DEFAULT 'open',
            action_plan TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            FOREIGN KEY (assessment_id) REFERENCES kam_assessments(id)
        )''')

        # Audit Programme
        c.execute('''CREATE TABLE IF NOT EXISTS kam_audit_plans (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            iso_standard TEXT,
            audit_type TEXT NOT NULL,
            scope TEXT,
            auditor TEXT,
            scheduled_date DATE,
            frequency TEXT DEFAULT 'jaarlijks',
            status TEXT DEFAULT 'planned',
            result TEXT,
            notes TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )''')

        # Management Reviews
        c.execute('''CREATE TABLE IF NOT EXISTS kam_mgmt_reviews (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            review_date DATE,
            review_type TEXT DEFAULT 'periodiek',
            kpi_summary TEXT,
            input_summary TEXT,
            decisions TEXT,
            followup_date DATE,
            status TEXT DEFAULT 'planned',
            notes TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )''')

        # Continu Verbetering (PDCA)
        c.execute('''CREATE TABLE IF NOT EXISTS kam_improvements (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            title TEXT NOT NULL,
            iso_standard TEXT,
            description TEXT,
            pdca_stage TEXT DEFAULT 'plan',
            priority TEXT DEFAULT 'medium',
            metric_before TEXT,
            metric_target TEXT,
            metric_after TEXT,
            owner TEXT,
            status TEXT DEFAULT 'open',
            notes TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )''')

        # Indexes
        c.execute('CREATE INDEX IF NOT EXISTS idx_kam_sa_iso ON kam_assessments(iso_standard)')
        c.execute('CREATE INDEX IF NOT EXISTS idx_kam_gap_status ON kam_gaps(status)')
        c.execute('CREATE INDEX IF NOT EXISTS idx_kam_gap_risk ON kam_gaps(risk_level)')
        c.execute('CREATE INDEX IF NOT EXISTS idx_kam_aud_status ON kam_audit_plans(status)')
        c.execute('CREATE INDEX IF NOT EXISTS idx_kam_imp_pdca ON kam_improvements(pdca_stage)')

        conn.commit()
        conn.close()
        print("[OK] KAM management tables initialized")
    except Exception as e:
        print(f"[WARN] init_kam_db: {e}")


# ─── Route Registration ──────────────────────────────────────────────────

def register_kam_routes(app, page_fn, BASE_PATH="/hseq-dashboard"):
    """Register all KAM management routes."""
    _page = page_fn

    @app.route(BASE_PATH + '/kam')
    def kam_dashboard_page():
        return _page(KAM_DASHBOARD_TEMPLATE.replace('__BP__', BASE_PATH),
                     page_title='KAM Management', page_subtitle='FASE 5 — ISO 9001/14001/45001 Self-Assessment, Gap Analyse, Audit Programma, Management Review, PDCA', active='kam')

    # ─── Dashboard Stats ───
    @app.route(BASE_PATH + '/api/kam/dashboard')
    def kam_api_dashboard():
        db = get_db()
        try:
            ta = db.execute("SELECT COUNT(*) as c FROM kam_assessments").fetchone()['c']
            avg = db.execute("SELECT AVG(total_score) as s FROM kam_assessments").fetchone()['s']
            og = db.execute("SELECT COUNT(*) as c FROM kam_gaps WHERE status != 'closed'").fetchone()['c']
            cg = db.execute("SELECT COUNT(*) as c FROM kam_gaps WHERE status != 'closed' AND risk_level IN ('high','critical')").fetchone()['c']
            aud_t = db.execute("SELECT COUNT(*) as c FROM kam_audit_plans").fetchone()['c']
            aud_c = db.execute("SELECT COUNT(*) as c FROM kam_audit_plans WHERE status='completed'").fetchone()['c']
            imp_t = db.execute("SELECT COUNT(*) as c FROM kam_improvements").fetchone()['c']
            imp_a = db.execute("SELECT COUNT(*) as c FROM kam_improvements WHERE status IN ('open','in_progress')").fetchone()['c']
            rev_t = db.execute("SELECT COUNT(*) as c FROM kam_mgmt_reviews").fetchone()['c']
            rev_c = db.execute("SELECT COUNT(*) as c FROM kam_mgmt_reviews WHERE status='completed'").fetchone()['c']
            return jsonify({
                'total_assessments': ta, 'avg_score': round(avg, 1) if avg else 0,
                'open_gaps': og, 'critical_gaps': cg,
                'total_audits': aud_t, 'audits_completed': aud_c,
                'total_improvements': imp_t, 'improvements_active': imp_a,
                'total_reviews': rev_t, 'reviews_completed': rev_c
            })
        finally:
            db.close()

    # ─── Clauses (static) ───
    @app.route(BASE_PATH + '/api/kam/clauses')
    def kam_api_clauses():
        iso = request.args.get('iso_standard', '')
        if iso not in ISO_CLAUSES:
            return jsonify({'error': 'Unknown ISO standard'}), 400
        clauses = ISO_CLAUSES[iso]['clauses']
        return jsonify([{'clause_ref': ref, 'clause_title': title} for ref, title in clauses])

    # ─── Self-Assessments CRUD ───
    @app.route(BASE_PATH + '/api/kam/assessments')
    def kam_api_assessments_list():
        db = get_db()
        try:
            q = 'SELECT * FROM kam_assessments WHERE 1=1'
            p = []
            iso = request.args.get('iso_standard')
            if iso:
                q += ' AND iso_standard = ?'; p.append(iso)
            q += ' ORDER BY created_at DESC'
            limit = request.args.get('limit', type=int)
            if limit:
                q += ' LIMIT ?'; p.append(limit)
            rows = db.execute(q, p).fetchall()
            return jsonify([dict(r) for r in rows])
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/assessments/<int:aid>')
    def kam_api_assessment_get(aid):
        db = get_db()
        try:
            d = db.execute('SELECT * FROM kam_assessments WHERE id=?', (aid,)).fetchone()
            if not d:
                return jsonify({'error': 'Not found'}), 404
            return jsonify(dict(d))
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/assessments', methods=['POST'])
    def kam_api_assessment_create():
        data = request.get_json(force=True)
        iso = data.get('iso_standard', '')
        clauses = data.get('clauses', [])
        if not iso or not clauses:
            return jsonify({'error': 'iso_standard and clauses required'}), 400

        total = sum(c.get('score', 0) for c in clauses)
        max_score = len(clauses) * 5
        pct = round((total / max_score * 100), 1) if max_score > 0 else 0

        db = get_db()
        try:
            cur = db.execute(
                'INSERT INTO kam_assessments (iso_standard, assessor, scope, clauses, total_score) VALUES (?,?,?,?,?)',
                (iso, data.get('assessor', 'HSEQ Manager'), data.get('scope', ''),
                 json.dumps(clauses, ensure_ascii=False), pct)
            )
            aid = cur.lastrowid

            # Auto-generate gaps for non-compliant clauses
            for c in clauses:
                gap = c.get('gap', 'none')
                if gap != 'none':
                    risk = 'low' if gap == 'low' else ('medium' if gap == 'medium' else ('high' if gap == 'high' else 'critical'))
                    db.execute(
                        'INSERT INTO kam_gaps (iso_standard, assessment_id, clause_ref, clause_title, description, risk_level) VALUES (?,?,?,?,?,?)',
                        (iso, aid, c.get('clause_ref', ''), c.get('clause_title', ''),
                         c.get('evidence', ''), risk)
                    )

            # Deliverable lifecycle integration
            try:
                dlv_type = 'audit_report' if 'audit' in iso.lower() else 'inspection_checklist'
                db.execute(
                    'INSERT INTO dlv_lifecycle (title, type, service, status, description, created_by) VALUES (?,?,?,?,?,?)',
                    (f'ISO Self-Assessment — {iso}', dlv_type, 'kam', 'approved',
                     f'Assessment score: {pct}%, Assessor: {data.get("assessor","")}',
                     data.get('assessor', 'system'))
                )
            except Exception:
                pass

            db.commit()
            return jsonify({'id': aid, 'total_score': pct}), 201
        finally:
            db.close()

    # ─── Gaps CRUD ───
    @app.route(BASE_PATH + '/api/kam/gaps')
    def kam_api_gaps_list():
        db = get_db()
        try:
            q = 'SELECT * FROM kam_gaps WHERE 1=1'
            p = []
            st = request.args.get('status')
            if st:
                q += ' AND status = ?'; p.append(st)
            q += ' ORDER BY risk_level DESC, created_at DESC'
            limit = request.args.get('limit', type=int)
            if limit:
                q += ' LIMIT ?'; p.append(limit)
            rows = db.execute(q, p).fetchall()
            return jsonify([dict(r) for r in rows])
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/gaps/<int:gid>')
    def kam_api_gap_get(gid):
        db = get_db()
        try:
            d = db.execute('SELECT * FROM kam_gaps WHERE id=?', (gid,)).fetchone()
            if not d:
                return jsonify({'error': 'Not found'}), 404
            return jsonify(dict(d))
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/gaps/<int:gid>', methods=['PUT'])
    def kam_api_gap_update(gid):
        data = request.get_json(force=True)
        db = get_db()
        try:
            db.execute('UPDATE kam_gaps SET description=?, risk_level=?, status=?, action_plan=?, updated_at=CURRENT_TIMESTAMP WHERE id=?',
                       (data.get('description', ''), data.get('risk_level', 'medium'),
                        data.get('status', 'open'), data.get('action_plan', ''), gid))
            db.commit()
            return jsonify({'ok': True})
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/gaps/generate', methods=['POST'])
    def kam_api_gaps_generate():
        """Generate gaps from latest assessments."""
        db = get_db()
        try:
            # Get latest assessment per ISO
            standards = ['ISO 9001:2015', 'ISO 14001:2015', 'ISO 45001:2018']
            generated = 0
            updated = 0
            for iso in standards:
                latest = db.execute('SELECT id, clauses FROM kam_assessments WHERE iso_standard=? ORDER BY created_at DESC LIMIT 1', (iso,)).fetchone()
                if not latest:
                    continue
                clauses = json.loads(latest['clauses'])
                for c in clauses:
                    gap = c.get('gap', 'none')
                    if gap == 'none':
                        continue
                    risk = {'low': 'low', 'medium': 'medium', 'high': 'high', 'critical': 'critical'}.get(gap, 'medium')
                    ref = c.get('clause_ref', '')
                    existing = db.execute('SELECT id FROM kam_gaps WHERE iso_standard=? AND clause_ref=? AND status != ?',
                                          (iso, ref, 'closed')).fetchone()
                    if existing:
                        db.execute('UPDATE kam_gaps SET risk_level=?, description=?, assessment_id=?, updated_at=CURRENT_TIMESTAMP WHERE id=?',
                                   (risk, c.get('evidence', ''), latest['id'], existing['id']))
                        updated += 1
                    else:
                        db.execute('INSERT INTO kam_gaps (iso_standard, assessment_id, clause_ref, clause_title, description, risk_level) VALUES (?,?,?,?,?,?)',
                                   (iso, latest['id'], ref, c.get('clause_title', ''), c.get('evidence', ''), risk))
                        generated += 1
            db.commit()
            return jsonify({'generated': generated, 'updated': updated})
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/gaps/export')
    def kam_api_gaps_export():
        """Export gaps as JSON report."""
        db = get_db()
        try:
            rows = db.execute('SELECT * FROM kam_gaps ORDER BY iso_standard, risk_level DESC').fetchall()
            gaps = [dict(r) for r in rows]
            report = {
                'title': 'KAM Gap Analyse Rapport',
                'generated_at': datetime.now().isoformat(),
                'total_gaps': len(gaps),
                'by_status': {},
                'by_risk': {},
                'gaps': gaps
            }
            for g in gaps:
                report['by_status'][g['status']] = report['by_status'].get(g['status'], 0) + 1
                report['by_risk'][g['risk_level']] = report['by_risk'].get(g['risk_level'], 0) + 1
            resp = jsonify(report)
            resp.headers['Content-Disposition'] = 'attachment; filename=kam_gap_report.json'
            return resp
        finally:
            db.close()

    # ─── Audit Plans CRUD ───
    @app.route(BASE_PATH + '/api/kam/audits')
    def kam_api_audits_list():
        db = get_db()
        try:
            q = 'SELECT * FROM kam_audit_plans WHERE 1=1 ORDER BY scheduled_date DESC'
            limit = request.args.get('limit', type=int)
            if limit:
                q += ' LIMIT ?'
                rows = db.execute(q, (limit,)).fetchall()
            else:
                rows = db.execute(q).fetchall()
            return jsonify([dict(r) for r in rows])
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/audits/<int:aid>')
    def kam_api_audit_get(aid):
        db = get_db()
        try:
            d = db.execute('SELECT * FROM kam_audit_plans WHERE id=?', (aid,)).fetchone()
            if not d:
                return jsonify({'error': 'Not found'}), 404
            return jsonify(dict(d))
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/audits', methods=['POST'])
    def kam_api_audit_create():
        data = request.get_json(force=True)
        db = get_db()
        try:
            cur = db.execute(
                'INSERT INTO kam_audit_plans (iso_standard, audit_type, scope, auditor, scheduled_date, frequency, notes) VALUES (?,?,?,?,?,?,?)',
                (data.get('iso_standard'), data.get('audit_type', 'internal'), data.get('scope', ''),
                 data.get('auditor', ''), data.get('scheduled_date', ''), data.get('frequency', 'jaarlijks'),
                 data.get('notes', ''))
            )
            db.commit()
            return jsonify({'id': cur.lastrowid}), 201
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/audits/<int:aid>', methods=['PUT'])
    def kam_api_audit_update(aid):
        data = request.get_json(force=True)
        db = get_db()
        try:
            db.execute('UPDATE kam_audit_plans SET status=?, result=?, notes=?, updated_at=CURRENT_TIMESTAMP WHERE id=?',
                       (data.get('status', 'planned'), data.get('result', ''), data.get('notes', ''), aid))
            db.commit()
            return jsonify({'ok': True})
        finally:
            db.close()

    # ─── Management Reviews CRUD ───
    @app.route(BASE_PATH + '/api/kam/reviews')
    def kam_api_reviews_list():
        db = get_db()
        try:
            q = 'SELECT * FROM kam_mgmt_reviews WHERE 1=1 ORDER BY created_at DESC'
            limit = request.args.get('limit', type=int)
            if limit:
                q += ' LIMIT ?'
                rows = db.execute(q, (limit,)).fetchall()
            else:
                rows = db.execute(q).fetchall()
            return jsonify([dict(r) for r in rows])
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/reviews/<int:rid>')
    def kam_api_review_get(rid):
        db = get_db()
        try:
            d = db.execute('SELECT * FROM kam_mgmt_reviews WHERE id=?', (rid,)).fetchone()
            if not d:
                return jsonify({'error': 'Not found'}), 404
            return jsonify(dict(d))
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/reviews', methods=['POST'])
    def kam_api_review_create():
        data = request.get_json(force=True)
        db = get_db()
        try:
            cur = db.execute(
                'INSERT INTO kam_mgmt_reviews (review_date, review_type, kpi_summary, input_summary, decisions, followup_date) VALUES (?,?,?,?,?,?)',
                (data.get('review_date', ''), data.get('review_type', 'periodiek'),
                 data.get('kpi_summary', ''), data.get('input_summary', ''),
                 data.get('decisions', ''), data.get('followup_date', ''))
            )
            db.commit()
            return jsonify({'id': cur.lastrowid}), 201
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/reviews/<int:rid>', methods=['PUT'])
    def kam_api_review_update(rid):
        data = request.get_json(force=True)
        db = get_db()
        try:
            db.execute('UPDATE kam_mgmt_reviews SET status=?, followup_date=?, notes=?, updated_at=CURRENT_TIMESTAMP WHERE id=?',
                       (data.get('status', 'planned'), data.get('followup_date', ''), data.get('notes', ''), rid))
            db.commit()
            return jsonify({'ok': True})
        finally:
            db.close()

    # ─── Improvements CRUD ───
    @app.route(BASE_PATH + '/api/kam/improvements')
    def kam_api_improvements_list():
        db = get_db()
        try:
            q = 'SELECT * FROM kam_improvements WHERE 1=1 ORDER BY created_at DESC'
            limit = request.args.get('limit', type=int)
            if limit:
                q += ' LIMIT ?'
                rows = db.execute(q, (limit,)).fetchall()
            else:
                rows = db.execute(q).fetchall()
            return jsonify([dict(r) for r in rows])
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/improvements/<int:iid>')
    def kam_api_improvement_get(iid):
        db = get_db()
        try:
            d = db.execute('SELECT * FROM kam_improvements WHERE id=?', (iid,)).fetchone()
            if not d:
                return jsonify({'error': 'Not found'}), 404
            return jsonify(dict(d))
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/improvements', methods=['POST'])
    def kam_api_improvement_create():
        data = request.get_json(force=True)
        db = get_db()
        try:
            cur = db.execute(
                'INSERT INTO kam_improvements (title, iso_standard, description, pdca_stage, priority, metric_before, metric_target, owner) VALUES (?,?,?,?,?,?,?,?)',
                (data.get('title', ''), data.get('iso_standard', ''), data.get('description', ''),
                 data.get('pdca_stage', 'plan'), data.get('priority', 'medium'),
                 data.get('metric_before', ''), data.get('metric_target', ''), data.get('owner', ''))
            )
            db.commit()
            return jsonify({'id': cur.lastrowid}), 201
        finally:
            db.close()

    @app.route(BASE_PATH + '/api/kam/improvements/<int:iid>', methods=['PUT'])
    def kam_api_improvement_update(iid):
        data = request.get_json(force=True)
        db = get_db()
        try:
            db.execute('UPDATE kam_improvements SET pdca_stage=?, status=?, metric_after=?, owner=?, notes=?, updated_at=CURRENT_TIMESTAMP WHERE id=?',
                       (data.get('pdca_stage', 'plan'), data.get('status', 'open'),
                        data.get('metric_after', ''), data.get('owner', ''),
                        data.get('notes', ''), iid))
            db.commit()
            return jsonify({'ok': True})
        finally:
            db.close()

    print("[OK] KAM management routes registered")
