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

const SECTORS = [
  { value: '', label: '— none —' },
  { value: 'energy', label: 'Energy' },
  { value: 'transport', label: 'Transport' },
  { value: 'banking', label: 'Banking / Financial' },
  { value: 'health', label: 'Healthcare' },
  { value: 'water', label: 'Water / Waste water' },
  { value: 'digital_infra', label: 'Digital infrastructure' },
  { value: 'public_admin', label: 'Public administration' },
];

const NIS2_SECTORS = new Set(['energy','transport','banking','health','water','digital_infra','public_admin']);
const DORA_SECTORS = new Set(['banking']);
const CYRA_SECTORS = new Set(['health']);

const REGS = [
  {
    id: 'gdpr', name: 'GDPR / AVG',
    full: 'General Data Protection Regulation',
    scope: 'always', badge: '#2563eb',
    categories: [
      {
        id: 'gdpr-legal', name: 'Legal basis & transparency',
        items: [
          { id: 'gdpr-001', text: 'Privacy statement published and up to date (Art. 13/14)', required: true },
          { id: 'gdpr-002', text: 'Processing register (Art. 30) maintained for all activities', required: true },
          { id: 'gdpr-003', text: 'Lawful basis identified for each processing activity', required: true },
          { id: 'gdpr-018', text: 'Cookie policy and consent mechanism compliant with ePrivacy', required: true },
          { id: 'gdpr-019', text: 'Retention periods defined and enforced per data category', required: true },
        ],
      },
      {
        id: 'gdpr-rights', name: 'Data subject rights',
        items: [
          { id: 'gdpr-004', text: 'Procedure for access requests (Art. 15) in place', required: true },
          { id: 'gdpr-005', text: 'Procedure for erasure requests (Art. 17) in place', required: true },
          { id: 'gdpr-006', text: 'Procedure for objection / restriction (Art. 21) in place', required: true },
        ],
      },
      {
        id: 'gdpr-security', name: 'Technical & organisational measures',
        items: [
          { id: 'gdpr-007', text: 'Personal data encrypted at rest', required: true },
          { id: 'gdpr-008', text: 'All data transfers use HTTPS / TLS', required: true },
          { id: 'gdpr-009', text: 'Access control: least-privilege principle applied', required: true },
          { id: 'gdpr-010', text: 'Password policy and MFA on systems holding personal data', required: true },
        ],
      },
      {
        id: 'gdpr-breach', name: 'Data breach procedure',
        items: [
          { id: 'gdpr-011', text: 'Breach response procedure documented (72-hr notification to AP)', required: true },
          { id: 'gdpr-012', text: 'Log of (potential) data breaches maintained', required: true },
        ],
      },
      {
        id: 'gdpr-processors', name: 'Processors & international transfers',
        items: [
          { id: 'gdpr-013', text: 'Data Processing Agreement (DPA) in place with all processors', required: true },
          { id: 'gdpr-014', text: 'Processor register maintained', required: true },
          { id: 'gdpr-015', text: 'Adequacy decisions or SCCs in place for transfers outside EEA', required: false, condition: 'Only required when transferring personal data outside the EEA' },
        ],
      },
      {
        id: 'gdpr-dpia', name: 'DPIA & DPO',
        items: [
          { id: 'gdpr-016', text: 'DPIA completed for high-risk processing activities', required: false, condition: 'Required for large-scale, sensitive-category, or profiling activities' },
          { id: 'gdpr-017', text: 'Data Protection Officer (DPO) appointed if mandatory', required: false, condition: 'Required for public authorities or large-scale sensitive processing' },
        ],
      },
    ],
  },
  {
    id: 'nis2', name: 'NIS2',
    full: 'Network & Information Security Directive 2',
    scope: 'conditional', badge: '#7c3aed',
    condition: 'Directly applicable if Lake-Project meets threshold (≥50 FTE or ≥€10M turnover in a critical sector). Also applies when contractually required by a NIS2-regulated client.',
    sectors: ['energy','transport','banking','health','water','digital_infra','public_admin'],
    categories: [
      {
        id: 'nis2-self', name: 'Self-assessment (threshold check)',
        scope: 'global',
        items: [
          { id: 'nis2-001', text: 'Threshold checked: <50 FTE and <€10M turnover — NIS2 does not directly apply', required: true },
          { id: 'nis2-002', text: 'Annual monitoring in place: track if growth approaches NIS2 threshold', required: true },
          { id: 'nis2-003', text: 'If threshold reached: registered with RDI (Rijksdienst Digitale Infrastructuur)', required: false, condition: 'Only required once threshold is met' },
        ],
      },
      {
        id: 'nis2-client', name: 'Client flow-down requirements',
        scope: 'client',
        items: [
          { id: 'nis2-004', text: 'Client NIS2 security requirements reviewed and accepted', required: true },
          { id: 'nis2-005', text: 'Incident reporting aligned with client requirements (<4hr / <24hr)', required: true },
          { id: 'nis2-006', text: 'Supply chain risk: own sub-processors / suppliers documented and assessed', required: true },
          { id: 'nis2-007', text: 'Penetration test or security audit completed per client requirement', required: false, condition: 'Depends on client contract' },
          { id: 'nis2-008', text: 'Certification (ISO 27001 / SOC 2 / equivalent) initiated per client requirement', required: false, condition: 'Depends on client contract' },
        ],
      },
    ],
  },
  {
    id: 'dora', name: 'DORA',
    full: 'Digital Operational Resilience Act',
    scope: 'conditional', badge: '#dc2626',
    condition: 'Applies when supplying ICT services to financial entities (banks, insurers, investment firms, payment / e-money institutions) regulated under DORA.',
    sectors: ['banking'],
    categories: [
      {
        id: 'dora-ict', name: 'ICT risk & resilience',
        scope: 'client',
        items: [
          { id: 'dora-001', text: 'ICT risk management policy documented and shared with financial client (Art. 5–16)', required: true },
          { id: 'dora-002', text: 'ICT incident reporting: <4hr initial notification to client', required: true },
          { id: 'dora-003', text: 'DORA contract clauses accepted: audit rights, SLA guarantees, exit plan', required: true },
          { id: 'dora-004', text: 'Business Continuity Plan (BCP) for ICT service delivery available', required: true },
        ],
      },
    ],
  },
  {
    id: 'iso27001', name: 'ISO 27001',
    full: 'ISO/IEC 27001:2022 — Information Security',
    scope: 'voluntary', badge: '#059669',
    description: 'Voluntary standard for information security management. May be contractually required by clients in regulated sectors.',
    categories: [
      {
        id: 'iso27001-controls', name: 'Core controls',
        scope: 'global',
        items: [
          { id: 'iso-001', text: 'Information security policy established and communicated', required: true },
          { id: 'iso-002', text: 'Asset register maintained (hardware, software, data assets)', required: true },
          { id: 'iso-003', text: 'Risk assessment completed with risk treatment plan', required: true },
          { id: 'iso-004', text: 'Access management: least-privilege, annual account review', required: true },
          { id: 'iso-005', text: 'Patch management: critical patches applied within 30 days', required: true },
          { id: 'iso-006', text: 'Backup procedure documented and restore tests completed', required: true },
          { id: 'iso-007', text: 'Supplier security assessments for critical vendors', required: true },
          { id: 'iso-008', text: 'Internal audit and management review completed annually', required: true },
        ],
      },
    ],
  },
  {
    id: 'cyra_zorg', name: 'CYRA-Zorg',
    full: 'CYRA-Zorg / NEN 7510',
    scope: 'conditional', badge: '#0891b2',
    condition: 'Applies when supplying ICT services to healthcare providers. NEN 7510 is mandatory for care organisations; suppliers receive contractual flow-down requirements.',
    sectors: ['health'],
    categories: [
      {
        id: 'cyra-controls', name: 'Healthcare ICT security',
        scope: 'client',
        items: [
          { id: 'cyra-001', text: 'NEN 7510 conformity statement or certificate available / in progress', required: true },
          { id: 'cyra-002', text: 'Patient data processed exclusively within EEA (data localisation)', required: true },
          { id: 'cyra-003', text: 'Supplementary DPA conforming to NEN 7512 signed with healthcare client', required: true },
        ],
      },
    ],
  },
];

function sectorLabel(value) {
  return SECTORS.find(s => s.value === value)?.label || value;
}

function CheckItem({ item, checked, onToggle, disabled }) {
  return (
    <label style={{
      display: 'flex', alignItems: 'flex-start', gap: 10, padding: '9px 0',
      borderBottom: '1px solid var(--border)',
      cursor: disabled ? 'default' : 'pointer',
    }}>
      <input
        type="checkbox"
        checked={checked}
        onChange={() => !disabled && onToggle()}
        disabled={disabled}
        style={{ marginTop: 2, flexShrink: 0 }}
      />
      <div style={{ flex: 1, fontSize: 13, lineHeight: 1.5 }}>
        <span style={{
          textDecoration: checked ? 'line-through' : 'none',
          color: checked ? 'var(--fg-muted)' : 'var(--fg)',
        }}>
          {item.text}
        </span>
        {item.condition && (
          <div style={{ fontSize: 11, color: 'var(--fg-subtle)', marginTop: 2, fontStyle: 'italic' }}>
            {item.condition}
          </div>
        )}
      </div>
      {!item.required && (
        <span style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--fg-subtle)', flexShrink: 0, marginTop: 3 }}>
          optional
        </span>
      )}
    </label>
  );
}

function RegSection({ reg, checks, selectedClient, clientActive, open, onToggle, onCheck }) {
  const nis2SelfDate = reg.id === 'nis2' ? (() => {
    const d1 = checks['nis2-001|global']?.updated_at;
    const d2 = checks['nis2-002|global']?.updated_at;
    const d = [d1, d2].filter(Boolean).sort().pop();
    const c1 = checks['nis2-001|global']?.checked;
    const c2 = checks['nis2-002|global']?.checked;
    return (c1 && c2 && d) ? d : null;
  })() : null;

  const activeItems = [];
  for (const cat of reg.categories) {
    const catScope = cat.scope || 'global';
    const isClient = catScope === 'client';
    if (!isClient || clientActive) {
      for (const item of cat.items) {
        const scope = isClient ? selectedClient : 'global';
        activeItems.push({ ...item, scope });
      }
    }
  }
  const total   = activeItems.length;
  const checked = activeItems.filter(i => checks[`${i.id}|${i.scope}`]?.checked).length;
  const pct     = total > 0 ? Math.round((checked / total) * 100) : 0;
  const done    = total > 0 && checked === total;
  const badgeColor = done ? '#059669' : reg.badge;

  return (
    <div className="card" style={{ margin: '0 0 12px 0', overflow: 'hidden' }}>
      {/* Section header */}
      <div
        onClick={onToggle}
        style={{
          display: 'flex', alignItems: 'center', gap: 12, padding: '14px 20px',
          cursor: 'pointer', userSelect: 'none',
          borderBottom: open ? '1px solid var(--border)' : 'none',
        }}
      >
        <span style={{
          padding: '2px 8px', borderRadius: 4,
          fontSize: 11, fontWeight: 600, fontFamily: 'var(--font-mono)',
          color: '#fff', background: badgeColor, flexShrink: 0,
        }}>
          {reg.name}
        </span>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 13, fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
            {reg.full}
          </div>
          <div style={{ fontSize: 11, color: 'var(--fg-muted)', marginTop: 1 }}>
            {total > 0
              ? `${checked} / ${total} items complete`
              : reg.scope === 'conditional' ? 'Conditional — select a matching client above' : ''
            }
            {reg.scope === 'voluntary' && <span style={{ marginLeft: 6, opacity: 0.6 }}>· voluntary</span>}
            {nis2SelfDate && (
              <span style={{ marginLeft: 12, color: '#059669', fontFamily: 'var(--font-mono)', fontSize: 10 }}>
                ✓ self-assessed {new Date(nis2SelfDate).toLocaleDateString('nl-NL')}
              </span>
            )}
          </div>
        </div>
        {total > 0 && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexShrink: 0 }}>
            <div style={{ width: 72, height: 4, background: 'var(--border)', borderRadius: 2, overflow: 'hidden' }}>
              <div style={{
                width: `${pct}%`, height: '100%', borderRadius: 2,
                background: badgeColor, transition: 'width 0.2s',
              }} />
            </div>
            <span style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: done ? '#059669' : 'var(--fg-muted)', width: 30, textAlign: 'right' }}>
              {pct}%
            </span>
          </div>
        )}
        <span style={{ fontSize: 11, color: 'var(--fg-subtle)', flexShrink: 0, marginLeft: 4 }}>
          {open ? '▾' : '▸'}
        </span>
      </div>

      {/* Section body */}
      {open && (
        <div style={{ padding: '0 20px' }}>
          {reg.condition && (
            <div style={{
              display: 'flex', gap: 8, padding: '10px 0',
              borderBottom: '1px solid var(--border)',
              fontSize: 12, color: 'var(--fg-muted)', lineHeight: 1.5,
            }}>
              <span style={{ flexShrink: 0 }}>ℹ</span>
              <span>{reg.condition}</span>
            </div>
          )}

          {reg.categories.map(cat => {
            const catScope   = cat.scope || 'global';
            const isClient   = catScope === 'client';
            const inactive   = isClient && !clientActive;
            const itemScope  = isClient ? selectedClient : 'global';

            return (
              <div key={cat.id} style={{ opacity: inactive ? 0.38 : 1 }}>
                <div style={{
                  fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.09em',
                  textTransform: 'uppercase', color: 'var(--fg-subtle)',
                  padding: '14px 0 4px', display: 'flex', alignItems: 'center', gap: 8,
                }}>
                  {cat.name}
                  {inactive && (
                    <span style={{ textTransform: 'none', letterSpacing: 0, fontStyle: 'italic' }}>
                      — {!selectedClient
                        ? 'select a client above to activate'
                        : `select a ${reg.sectors?.map(sectorLabel).join(' / ')} client`}
                    </span>
                  )}
                </div>
                {cat.items.map(item => (
                  <CheckItem
                    key={item.id}
                    item={item}
                    checked={!!(checks[`${item.id}|${itemScope}`]?.checked)}
                    onToggle={() => onCheck(item.id, itemScope)}
                    disabled={inactive}
                  />
                ))}
              </div>
            );
          })}
          <div style={{ height: 12 }} />
        </div>
      )}
    </div>
  );
}

function Compliance() {
  const [checks, setChecks]             = useState({});
  const [companies, setCompanies]       = useState([]);
  const [selectedClient, setSelectedClient] = useState('');
  const [open, setOpen]                 = useState({ gdpr: true, nis2: true, dora: false, iso27001: false, cyra_zorg: false });
  const { toast } = useApp();

  const loadChecks = useCallback(async (scope) => {
    try {
      const data = await API.get(`/compliance?scope=${encodeURIComponent(scope)}`);
      setChecks(prev => {
        const next = { ...prev };
        for (const row of data) next[`${row.check_id}|${row.scope}`] = row;
        return next;
      });
    } catch (e) { /* ignore */ }
  }, []);

  useEffect(() => {
    API.get('/companies').then(setCompanies).catch(() => {});
    loadChecks('global');
  }, [loadChecks]);

  useEffect(() => {
    if (selectedClient) loadChecks(selectedClient);
  }, [selectedClient, loadChecks]);

  const clientCo  = companies.find(c => c.id === selectedClient);
  const sector    = clientCo?.sector || '';
  const nis2Active = !!(selectedClient && NIS2_SECTORS.has(sector));
  const doraActive = !!(selectedClient && DORA_SECTORS.has(sector));
  const cyraActive = !!(selectedClient && CYRA_SECTORS.has(sector));

  function clientActiveFor(reg) {
    if (reg.id === 'nis2')      return nis2Active;
    if (reg.id === 'dora')      return doraActive;
    if (reg.id === 'cyra_zorg') return cyraActive;
    return false;
  }

  async function handleCheck(checkId, scope) {
    const key     = `${checkId}|${scope}`;
    const current = checks[key]?.checked ? 1 : 0;
    const next    = current ? 0 : 1;
    setChecks(prev => ({
      ...prev,
      [key]: { ...(prev[key] || {}), check_id: checkId, scope, checked: next, updated_at: new Date().toISOString() },
    }));
    try {
      await API.post('/compliance', { check_id: checkId, scope, checked: next });
    } catch (e) {
      setChecks(prev => ({ ...prev, [key]: { ...(prev[key] || {}), checked: current } }));
      toast(e.error || 'Error saving', 'error');
    }
  }

  const customerCompanies = companies.filter(c => c.type === 'customer' || c.type === 'both');

  return (
    <div className="page">
      <div className="page-header">
        <div>
          <h1 className="page-title">Compliance</h1>
          <div className="page-subtitle">GDPR · NIS2 · DORA · ISO 27001 · CYRA-Zorg</div>
        </div>
      </div>

      <div style={{
        display: 'flex', gap: 8, alignItems: 'flex-start', padding: '10px 14px',
        background: 'rgba(37,99,235,0.07)', border: '1px solid rgba(37,99,235,0.22)',
        borderRadius: 6, marginBottom: 20, fontSize: 12, color: 'var(--fg-muted)', lineHeight: 1.5,
      }}>
        <span style={{ flexShrink: 0, fontSize: 14 }}>⚖</span>
        <span>
          This checklist is a <strong>practical aide-mémoire</strong>, not legal advice.
          Compliance obligations depend on your specific situation. Consult a qualified legal advisor for binding guidance.
        </span>
      </div>

      <div className="card" style={{ margin: '0 0 16px 0' }}>
        <div style={{ padding: '14px 20px' }}>
          <div style={{ display: 'flex', alignItems: 'flex-end', gap: 16, flexWrap: 'wrap' }}>
            <div style={{ flex: '1 1 220px', maxWidth: 360 }}>
              <label className="field-label" style={{ display: 'block', marginBottom: 4 }}>
                Client context for conditional regulations
              </label>
              <select
                className="field-select"
                value={selectedClient}
                onChange={e => setSelectedClient(e.target.value)}
              >
                <option value="">— global (no client) —</option>
                {customerCompanies.map(co => (
                  <option key={co.id} value={co.id}>
                    {co.name}{co.sector ? ` · ${sectorLabel(co.sector)}` : ''}
                  </option>
                ))}
              </select>
            </div>
            {selectedClient && (
              <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', paddingBottom: 1 }}>
                {nis2Active && <Tag color="#7c3aed" label="NIS2 client" />}
                {doraActive && <Tag color="#dc2626" label="DORA client" />}
                {cyraActive && <Tag color="#0891b2" label="CYRA-Zorg client" />}
                {!nis2Active && !doraActive && !cyraActive && (
                  <span style={{ fontSize: 11, color: 'var(--fg-subtle)', fontStyle: 'italic', paddingBottom: 2 }}>
                    No conditional regs apply for this sector.
                    {!sector && ' Set sector in Companies → Edit.'}
                  </span>
                )}
              </div>
            )}
          </div>
        </div>
      </div>

      {REGS.map(reg => (
        <RegSection
          key={reg.id}
          reg={reg}
          checks={checks}
          selectedClient={selectedClient}
          clientActive={clientActiveFor(reg)}
          open={!!open[reg.id]}
          onToggle={() => setOpen(prev => ({ ...prev, [reg.id]: !prev[reg.id] }))}
          onCheck={handleCheck}
        />
      ))}
    </div>
  );
}

function Tag({ color, label }) {
  return (
    <span style={{
      padding: '3px 8px', borderRadius: 3,
      background: `${color}18`, color, border: `1px solid ${color}44`,
      fontSize: 11, fontFamily: 'var(--font-mono)', fontWeight: 600,
    }}>
      {label}
    </span>
  );
}

window.Compliance = Compliance;
