/* global React, API, useApp */
const { useState, useEffect, useCallback } = React;

const RISK_FLAGS = [
  { id: 'sensitive_categories',  label: 'Sensitive categories of data (health, biometric, criminal, ethnic origin, religious belief, etc.)' },
  { id: 'large_scale',           label: 'Large-scale processing (thousands of individuals, or systematic/continuous)' },
  { id: 'profiling',             label: 'Profiling or automated decision-making with legal or similarly significant effect' },
  { id: 'systematic_monitoring', label: 'Systematic monitoring of a publicly accessible area (CCTV, tracking, etc.)' },
  { id: 'children',              label: 'Data of children or other vulnerable persons' },
  { id: 'novel_tech',            label: 'Use of new or previously untested technology or organisational approach' },
  { id: 'combining_datasets',    label: 'Combining or cross-referencing datasets from multiple sources in a way not originally foreseen' },
  { id: 'prevent_rights',        label: 'Processing that could prevent individuals from exercising rights or accessing services' },
  { id: 'financial_at_scale',    label: 'Large-scale financial, creditworthiness, or fraud-related processing' },
  { id: 'location_tracking',     label: 'Systematic tracking of location or behaviour' },
];

const RISK_LEVELS  = ['low', 'medium', 'high'];
const RISK_COLORS  = { low: '#3FB950', medium: '#D29922', high: '#F85149' };
const SCOPE_OPTS   = ['< 50 individuals', '50–500 individuals', '500–5 000 individuals', '5 000–50 000 individuals', '> 50 000 individuals'];

const EMPTY = {
  activity_name: '', purpose: '', data_categories: '', data_subjects: '', scope_size: '',
  risk_flags: [], risks: [], mitigations: '', residual_risk: 'low',
  dpia_required: false, conclusion: '', assessor: 'Alexander van der Plas',
  assessed_at: new Date().toISOString().slice(0, 10), next_review_at: '',
};

function RiskBadge({ level }) {
  return (
    <span style={{
      fontFamily: 'var(--font-mono)', fontSize: 9, fontWeight: 700, letterSpacing: '0.08em',
      textTransform: 'uppercase', padding: '2px 7px', borderRadius: 20, border: '1px solid',
      color: RISK_COLORS[level] || RISK_COLORS.low,
      borderColor: `${RISK_COLORS[level] || RISK_COLORS.low}44`,
      background: `${RISK_COLORS[level] || RISK_COLORS.low}12`,
    }}>
      {level || 'low'} risk
    </span>
  );
}

function DPIAModal({ assessment, onSave, onClose }) {
  const [form, setForm] = useState(() => {
    if (!assessment) return { ...EMPTY };
    return {
      ...EMPTY,
      ...assessment,
      risk_flags: (() => { try { return JSON.parse(assessment.risk_flags || '[]'); } catch { return []; } })(),
      risks:      (() => { try { return JSON.parse(assessment.risks_json || '[]'); } catch { return []; } })(),
      dpia_required: !!assessment.dpia_required,
    };
  });
  const [busy, setBusy] = useState(false);
  const [step, setStep] = useState(1);
  const { toast } = useApp();

  const f  = k => e => setForm(p => ({ ...p, [k]: e.target.value }));
  const fb = k => e => setForm(p => ({ ...p, [k]: e.target.checked }));

  const flagCount = form.risk_flags.length;
  const dpiaRequired = flagCount >= 2 || form.dpia_required;

  function toggleFlag(id) {
    setForm(p => ({
      ...p,
      risk_flags: p.risk_flags.includes(id) ? p.risk_flags.filter(f => f !== id) : [...p.risk_flags, id],
    }));
  }

  function addRisk() {
    setForm(p => ({
      ...p,
      risks: [...p.risks, { id: Date.now(), description: '', probability: 'low', impact: 'low', mitigation: '' }],
    }));
  }

  function updateRisk(idx, key, val) {
    setForm(p => {
      const risks = [...p.risks];
      risks[idx] = { ...risks[idx], [key]: val };
      return { ...p, risks };
    });
  }

  function removeRisk(idx) {
    setForm(p => ({ ...p, risks: p.risks.filter((_, i) => i !== idx) }));
  }

  function computeResidualRisk() {
    if (!form.risks.length) return 'low';
    const scores = { low: 1, medium: 2, high: 3 };
    const max = Math.max(...form.risks.map(r => scores[r.probability] * scores[r.impact]));
    if (max >= 6) return 'high';
    if (max >= 3) return 'medium';
    return 'low';
  }

  useEffect(() => {
    if (step === 3) setForm(p => ({ ...p, residual_risk: computeResidualRisk(), dpia_required: dpiaRequired }));
  }, [step]);

  async function save(e) {
    e.preventDefault();
    setBusy(true);
    try {
      const payload = { ...form, dpia_required: dpiaRequired };
      assessment?.id
        ? await API.put(`/dpia/${assessment.id}`, payload)
        : await API.post('/dpia', payload);
      onSave();
    } catch (ex) { toast(ex?.error || 'Error saving', 'error'); }
    finally { setBusy(false); }
  }

  const steps = ['Scope & data', 'Risk indicators', 'Risks & mitigations', 'Conclusion'];

  return (
    <div className="modal-overlay" onClick={e => e.target === e.currentTarget && onClose()}>
      <div className="modal" style={{ maxWidth: 680, width: '94%', maxHeight: '92vh', overflowY: 'auto' }}>
        <div className="modal-head">
          <span className="modal-title">{assessment?.id ? 'Edit DPIA assessment' : 'New DPIA self-assessment'}</span>
          <button className="modal-close" onClick={onClose}>✕</button>
        </div>

        {/* Step indicators */}
        <div style={{ display: 'flex', borderBottom: '1px solid var(--border)', background: 'var(--surface-raised)' }}>
          {steps.map((s, i) => (
            <button
              key={i}
              onClick={() => setStep(i + 1)}
              style={{
                flex: 1, padding: '10px 4px', border: 'none', cursor: 'pointer',
                background: 'none', fontSize: 10, fontFamily: 'var(--font-mono)',
                letterSpacing: '0.08em', textTransform: 'uppercase',
                color: step === i + 1 ? 'var(--signal)' : 'var(--fg-subtle)',
                borderBottom: step === i + 1 ? '2px solid var(--signal)' : '2px solid transparent',
                transition: 'color 120ms',
              }}
            >
              {i + 1}. {s}
            </button>
          ))}
        </div>

        <form onSubmit={save}>
          {/* STEP 1 — Scope */}
          {step === 1 && (
            <div className="modal-body" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0 16px' }}>
              <div className="field" style={{ gridColumn: '1/-1' }}>
                <label className="field-label">Processing activity name *</label>
                <input className="field-input" required value={form.activity_name} onChange={f('activity_name')} placeholder="e.g. Invoice administration" />
              </div>
              <div className="field" style={{ gridColumn: '1/-1' }}>
                <label className="field-label">Purpose of processing</label>
                <textarea className="field-input" rows={2} value={form.purpose} onChange={f('purpose')} placeholder="Why is this data processed?" style={{ resize: 'vertical' }} />
              </div>
              <div className="field" style={{ gridColumn: '1/-1' }}>
                <label className="field-label">Categories of personal data</label>
                <textarea className="field-input" rows={2} value={form.data_categories} onChange={f('data_categories')} placeholder="e.g. Name, email, invoice data, company address" style={{ resize: 'vertical' }} />
              </div>
              <div className="field">
                <label className="field-label">Data subjects</label>
                <input className="field-input" value={form.data_subjects} onChange={f('data_subjects')} placeholder="e.g. Client contacts" />
              </div>
              <div className="field">
                <label className="field-label">Number of individuals (approx.)</label>
                <select className="field-select" value={form.scope_size} onChange={f('scope_size')}>
                  <option value="">— select —</option>
                  {SCOPE_OPTS.map(o => <option key={o} value={o}>{o}</option>)}
                </select>
              </div>
              <div className="field">
                <label className="field-label">Assessed by</label>
                <input className="field-input" value={form.assessor} onChange={f('assessor')} />
              </div>
              <div className="field">
                <label className="field-label">Assessment date</label>
                <input className="field-input" type="date" value={form.assessed_at} onChange={f('assessed_at')} />
              </div>
              <div className="field">
                <label className="field-label">Next review date</label>
                <input className="field-input" type="date" value={form.next_review_at} onChange={f('next_review_at')} />
              </div>
            </div>
          )}

          {/* STEP 2 — Risk indicators */}
          {step === 2 && (
            <div className="modal-body">
              <div style={{ fontSize: 12, color: 'var(--fg-muted)', marginBottom: 16, lineHeight: 1.65 }}>
                Check all indicators that apply to this processing activity. A DPIA is <strong style={{ color: 'var(--fg)' }}>mandatory</strong> under GDPR Art. 35 if <strong style={{ color: 'var(--fg)' }}>2 or more</strong> of these apply (AP / EDPB guidance). Currently: <strong style={{ color: flagCount >= 2 ? 'var(--danger)' : 'var(--ok)' }}>{flagCount} selected</strong>.
              </div>
              {RISK_FLAGS.map(rf => (
                <label key={rf.id} style={{ display: 'flex', alignItems: 'flex-start', gap: 10, padding: '10px 0', borderBottom: '1px solid var(--border)', cursor: 'pointer' }}>
                  <input
                    type="checkbox"
                    checked={form.risk_flags.includes(rf.id)}
                    onChange={() => toggleFlag(rf.id)}
                    style={{ marginTop: 2, flexShrink: 0 }}
                  />
                  <span style={{ fontSize: 12, color: form.risk_flags.includes(rf.id) ? 'var(--fg)' : 'var(--fg-muted)', lineHeight: 1.55 }}>
                    {rf.label}
                  </span>
                </label>
              ))}
              {flagCount >= 2 && (
                <div style={{ marginTop: 16, padding: '10px 14px', background: 'rgba(248,81,73,0.08)', border: '1px solid rgba(248,81,73,0.3)', borderRadius: 4, fontSize: 12, color: 'var(--danger)', lineHeight: 1.55 }}>
                  <strong>DPIA required.</strong> {flagCount} risk indicators are present. A full DPIA must be completed before starting or significantly changing this processing activity.
                </div>
              )}
              {flagCount === 1 && (
                <div style={{ marginTop: 16, padding: '10px 14px', background: 'rgba(210,153,34,0.08)', border: '1px solid rgba(210,153,34,0.3)', borderRadius: 4, fontSize: 12, color: 'var(--warning, #D29922)', lineHeight: 1.55 }}>
                  1 risk indicator. A DPIA is not yet mandatory but consider completing one as good practice.
                </div>
              )}
              {flagCount === 0 && (
                <div style={{ marginTop: 16, padding: '10px 14px', background: 'rgba(63,185,80,0.08)', border: '1px solid rgba(63,185,80,0.3)', borderRadius: 4, fontSize: 12, color: 'var(--ok)', lineHeight: 1.55 }}>
                  No risk indicators selected. A DPIA is not required for this activity.
                </div>
              )}
            </div>
          )}

          {/* STEP 3 — Risks & mitigations */}
          {step === 3 && (
            <div className="modal-body">
              <div style={{ fontSize: 12, color: 'var(--fg-muted)', marginBottom: 16, lineHeight: 1.65 }}>
                List specific risks to data subjects. For each risk, estimate the probability and impact, and describe the mitigation in place.
              </div>

              {form.risks.map((risk, i) => (
                <div key={risk.id || i} style={{ background: 'var(--surface-raised)', border: '1px solid var(--border)', borderRadius: 4, padding: '14px 16px', marginBottom: 10 }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
                    <span style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--fg-subtle)', textTransform: 'uppercase', letterSpacing: '0.1em' }}>Risk {i + 1}</span>
                    <button type="button" className="btn btn--danger btn--sm" onClick={() => removeRisk(i)}>Remove</button>
                  </div>
                  <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '8px 12px' }}>
                    <div className="field" style={{ gridColumn: '1/-1', marginBottom: 0 }}>
                      <label className="field-label">Risk description</label>
                      <input className="field-input" value={risk.description} onChange={e => updateRisk(i, 'description', e.target.value)} placeholder="e.g. Unauthorised access to invoice data" />
                    </div>
                    <div className="field" style={{ marginBottom: 0 }}>
                      <label className="field-label">Probability</label>
                      <select className="field-select" value={risk.probability} onChange={e => updateRisk(i, 'probability', e.target.value)}>
                        {RISK_LEVELS.map(l => <option key={l} value={l}>{l.charAt(0).toUpperCase() + l.slice(1)}</option>)}
                      </select>
                    </div>
                    <div className="field" style={{ marginBottom: 0 }}>
                      <label className="field-label">Impact</label>
                      <select className="field-select" value={risk.impact} onChange={e => updateRisk(i, 'impact', e.target.value)}>
                        {RISK_LEVELS.map(l => <option key={l} value={l}>{l.charAt(0).toUpperCase() + l.slice(1)}</option>)}
                      </select>
                    </div>
                    <div className="field" style={{ marginBottom: 0 }}>
                      <label className="field-label">Combined</label>
                      <div style={{ padding: '8px 0', fontSize: 12 }}>
                        {(() => {
                          const s = { low: 1, medium: 2, high: 3 };
                          const v = s[risk.probability] * s[risk.impact];
                          const lvl = v >= 6 ? 'high' : v >= 3 ? 'medium' : 'low';
                          return <RiskBadge level={lvl} />;
                        })()}
                      </div>
                    </div>
                    <div className="field" style={{ gridColumn: '1/-1', marginBottom: 0 }}>
                      <label className="field-label">Mitigation measure</label>
                      <input className="field-input" value={risk.mitigation} onChange={e => updateRisk(i, 'mitigation', e.target.value)} placeholder="e.g. AES-256 encryption at rest, passkey auth" />
                    </div>
                  </div>
                </div>
              ))}

              <button type="button" className="btn btn--ghost" style={{ marginBottom: 16 }} onClick={addRisk}>
                + Add risk
              </button>

              <div className="field">
                <label className="field-label">Additional mitigations / notes</label>
                <textarea className="field-input" rows={3} value={form.mitigations} onChange={f('mitigations')} placeholder="Any further organisational or technical measures not captured above" style={{ resize: 'vertical' }} />
              </div>

              {form.risks.length > 0 && (
                <div style={{ padding: '10px 14px', background: 'var(--surface-raised)', border: '1px solid var(--border)', borderRadius: 4, fontSize: 12, color: 'var(--fg-muted)', display: 'flex', alignItems: 'center', gap: 8 }}>
                  Computed residual risk: <RiskBadge level={computeResidualRisk()} />
                </div>
              )}
            </div>
          )}

          {/* STEP 4 — Conclusion */}
          {step === 4 && (
            <div className="modal-body">
              <div style={{ display: 'flex', gap: 12, marginBottom: 20, flexWrap: 'wrap' }}>
                <div style={{ flex: 1, minWidth: 180, padding: '14px 16px', background: 'var(--surface-raised)', border: '1px solid var(--border)', borderRadius: 4 }}>
                  <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--fg-subtle)', textTransform: 'uppercase', letterSpacing: '0.1em', marginBottom: 6 }}>Risk indicators</div>
                  <div style={{ fontSize: 20, fontWeight: 700, color: flagCount >= 2 ? 'var(--danger)' : flagCount === 1 ? '#D29922' : 'var(--ok)' }}>{flagCount}</div>
                  <div style={{ fontSize: 11, color: 'var(--fg-muted)', marginTop: 2 }}>{flagCount >= 2 ? 'DPIA required' : flagCount === 1 ? 'Consider DPIA' : 'No DPIA required'}</div>
                </div>
                <div style={{ flex: 1, minWidth: 180, padding: '14px 16px', background: 'var(--surface-raised)', border: '1px solid var(--border)', borderRadius: 4 }}>
                  <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--fg-subtle)', textTransform: 'uppercase', letterSpacing: '0.1em', marginBottom: 8 }}>Residual risk</div>
                  <RiskBadge level={form.residual_risk || computeResidualRisk()} />
                </div>
                <div style={{ flex: 1, minWidth: 180, padding: '14px 16px', background: 'var(--surface-raised)', border: '1px solid var(--border)', borderRadius: 4 }}>
                  <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--fg-subtle)', textTransform: 'uppercase', letterSpacing: '0.1em', marginBottom: 6 }}>Risks identified</div>
                  <div style={{ fontSize: 20, fontWeight: 700, color: 'var(--fg)' }}>{form.risks.length}</div>
                  <div style={{ fontSize: 11, color: 'var(--fg-muted)', marginTop: 2 }}>{form.risks.filter(r => { const s = { low: 1, medium: 2, high: 3 }; return s[r.probability] * s[r.impact] >= 6; }).length} high-severity</div>
                </div>
              </div>

              <div className="field">
                <label className="field-label">Residual risk level (override if needed)</label>
                <select className="field-select" value={form.residual_risk} onChange={f('residual_risk')}>
                  {RISK_LEVELS.map(l => <option key={l} value={l}>{l.charAt(0).toUpperCase() + l.slice(1)}</option>)}
                </select>
              </div>

              <div className="field">
                <label style={{ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer', fontSize: 13, color: 'var(--fg-muted)' }}>
                  <input type="checkbox" checked={form.dpia_required} onChange={fb('dpia_required')} />
                  Full DPIA required (override — automatically set if ≥ 2 risk indicators)
                </label>
              </div>

              <div className="field">
                <label className="field-label">Conclusion &amp; decision</label>
                <textarea
                  className="field-input"
                  rows={4}
                  value={form.conclusion}
                  onChange={f('conclusion')}
                  placeholder={dpiaRequired
                    ? 'DPIA required. Describe the outcome: can processing proceed, is DPO consultation needed, what conditions apply?'
                    : 'Processing can proceed. Summarise why no DPIA is required and what safeguards are in place.'}
                  style={{ resize: 'vertical' }}
                />
              </div>

              {dpiaRequired && (
                <div style={{ padding: '10px 14px', background: 'rgba(248,81,73,0.08)', border: '1px solid rgba(248,81,73,0.3)', borderRadius: 4, fontSize: 12, color: 'var(--danger)', lineHeight: 1.65 }}>
                  <strong>Action required:</strong> A full DPIA must be completed and documented. If residual risk remains high after mitigation, consult the Autoriteit Persoonsgegevens before starting processing (GDPR Art. 36). AP prior consultation: <a href="mailto:informatiebeveiliging@ap.nl" style={{ color: 'var(--danger)' }}>informatiebeveiliging@ap.nl</a>
                </div>
              )}
            </div>
          )}

          <div style={{ padding: '12px 20px', borderTop: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', gap: 8 }}>
            <div style={{ display: 'flex', gap: 6 }}>
              {step > 1 && <button type="button" className="btn btn--ghost" onClick={() => setStep(s => s - 1)}>← Back</button>}
            </div>
            <div style={{ display: 'flex', gap: 6 }}>
              <button type="button" className="btn btn--ghost" onClick={onClose}>Cancel</button>
              {step < 4
                ? <button type="button" className="btn btn--primary" onClick={() => setStep(s => s + 1)}>Next →</button>
                : <button type="submit" className="btn btn--primary" disabled={busy}>{busy ? 'Saving…' : 'Save assessment'}</button>
              }
            </div>
          </div>
        </form>
      </div>
    </div>
  );
}

function DPIA() {
  const [assessments, setAssessments] = useState([]);
  const [modal, setModal]             = useState(null);
  const [loading, setLoading]         = useState(true);
  const { toast } = useApp();

  const load = useCallback(() => {
    setLoading(true);
    API.get('/dpia').then(r => { setAssessments(r || []); setLoading(false); }).catch(() => setLoading(false));
  }, []);

  useEffect(() => { load(); }, [load]);

  async function handleDelete(a) {
    if (!confirm(`Delete DPIA assessment "${a.activity_name}"? This cannot be undone.`)) return;
    try {
      await API.del(`/dpia/${a.id}`);
      setAssessments(prev => prev.filter(x => x.id !== a.id));
      toast('Deleted');
    } catch (ex) { toast(ex?.error || 'Error', 'error'); }
  }

  function handleSave() { setModal(null); load(); toast('DPIA assessment saved'); }

  async function openEdit(a) {
    try {
      const full = await API.get(`/dpia/${a.id}`);
      setModal(full);
    } catch { toast('Error loading assessment', 'error'); }
  }

  const fmtDate = d => d ? new Date(d).toLocaleDateString('nl-NL', { day: '2-digit', month: 'short', year: 'numeric' }) : '—';

  const highCount = assessments.filter(a => a.residual_risk === 'high').length;
  const dpiaCount = assessments.filter(a => a.dpia_required).length;

  return (
    <div className="page">
      <div className="page-header">
        <div>
          <h1 className="page-title">DPIA self-assessments</h1>
          <div className="page-subtitle">Data Protection Impact Assessment — GDPR Art. 35</div>
        </div>
        <button className="btn btn--primary" onClick={() => setModal('new')}>+ New assessment</button>
      </div>

      <div style={{
        display: 'flex', gap: 8, padding: '10px 14px', marginBottom: 20,
        background: 'rgba(37,99,235,0.07)', border: '1px solid rgba(37,99,235,0.22)',
        borderRadius: 6, fontSize: 12, color: 'var(--fg-muted)', lineHeight: 1.5,
      }}>
        <span style={{ flexShrink: 0, fontSize: 14 }}>ℹ</span>
        <span>
          A DPIA is <strong>required</strong> when processing is likely to result in a high risk (GDPR Art. 35). Use the self-assessment to identify risk indicators. If 2 or more apply, complete a full DPIA before processing begins. This self-assessment tool helps you decide — it does not substitute a formal DPIA.
        </span>
      </div>

      {(highCount > 0 || dpiaCount > 0) && (
        <div style={{ display: 'flex', gap: 8, marginBottom: 16, flexWrap: 'wrap' }}>
          {dpiaCount > 0 && <div style={{ padding: '8px 14px', background: 'rgba(248,81,73,0.08)', border: '1px solid rgba(248,81,73,0.3)', borderRadius: 4, fontSize: 12, color: '#F85149' }}>{dpiaCount} activit{dpiaCount === 1 ? 'y requires' : 'ies require'} a full DPIA</div>}
          {highCount > 0 && <div style={{ padding: '8px 14px', background: 'rgba(210,153,34,0.08)', border: '1px solid rgba(210,153,34,0.3)', borderRadius: 4, fontSize: 12, color: '#D29922' }}>{highCount} high residual risk</div>}
        </div>
      )}

      {loading ? (
        <div style={{ color: 'var(--fg-subtle)', padding: 24, fontSize: 13 }}>Loading…</div>
      ) : assessments.length === 0 ? (
        <div className="card">
          <div style={{ padding: 40, textAlign: 'center' }}>
            <div style={{ fontSize: 14, fontWeight: 500, color: 'var(--fg)', marginBottom: 8 }}>No assessments yet</div>
            <div style={{ fontSize: 12, color: 'var(--fg-muted)', marginBottom: 20, maxWidth: 440, margin: '0 auto 20px', lineHeight: 1.6 }}>
              Run a self-assessment for each processing activity in your Art. 30 register to determine whether a formal DPIA is required.
            </div>
            <button className="btn btn--primary" onClick={() => setModal('new')}>Start first assessment</button>
          </div>
        </div>
      ) : (
        <div className="card" style={{ margin: 0 }}>
          <div className="table-wrap">
            <table className="data-table">
              <thead>
                <tr>
                  <th>Processing activity</th>
                  <th>Risk indicators</th>
                  <th>Residual risk</th>
                  <th>DPIA required</th>
                  <th>Assessed</th>
                  <th>Next review</th>
                  <th style={{ width: 80 }}></th>
                </tr>
              </thead>
              <tbody>
                {assessments.map(a => {
                  const flags = (() => { try { return JSON.parse(a.risk_flags || '[]'); } catch { return []; } })();
                  return (
                    <tr key={a.id} onClick={() => openEdit(a)} style={{ cursor: 'pointer' }}>
                      <td style={{ fontWeight: 500, fontSize: 13 }}>{a.activity_name}</td>
                      <td>
                        <span style={{
                          fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 600,
                          color: flags.length >= 2 ? '#F85149' : flags.length === 1 ? '#D29922' : 'var(--fg-subtle)',
                        }}>{flags.length}</span>
                        <span style={{ fontSize: 11, color: 'var(--fg-subtle)', marginLeft: 4 }}>/ {RISK_FLAGS.length}</span>
                      </td>
                      <td><RiskBadge level={a.residual_risk} /></td>
                      <td>
                        {a.dpia_required
                          ? <span style={{ fontSize: 11, fontFamily: 'var(--font-mono)', fontWeight: 700, color: '#F85149' }}>Yes</span>
                          : <span style={{ fontSize: 11, color: 'var(--fg-subtle)' }}>No</span>
                        }
                      </td>
                      <td style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--fg-muted)' }}>{fmtDate(a.assessed_at)}</td>
                      <td style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: a.next_review_at && new Date(a.next_review_at) < new Date() ? '#F85149' : 'var(--fg-muted)' }}>
                        {fmtDate(a.next_review_at)}
                      </td>
                      <td onClick={e => e.stopPropagation()}>
                        <button className="btn btn--danger btn--sm" onClick={() => handleDelete(a)}>Del</button>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
          <div style={{ padding: '10px 20px', borderTop: '1px solid var(--border)', fontSize: 11, color: 'var(--fg-subtle)', fontFamily: 'var(--font-mono)' }}>
            {assessments.length} assessment{assessments.length === 1 ? '' : 's'} · GDPR Art. 35 · Screening tool only
          </div>
        </div>
      )}

      {(modal === 'new' || (modal && typeof modal === 'object')) && (
        <DPIAModal
          assessment={modal === 'new' ? null : modal}
          onSave={handleSave}
          onClose={() => setModal(null)}
        />
      )}
    </div>
  );
}
window.DPIA = DPIA;
