/**
 * ComplianceAuditPage — Compliance & AI-Audit dashboard.
 *
 * Tab A: AI Data-Flow Log  — FormGeneratorTable + content view modal + download
 * Tab B: Security / GDPR Audit Log — FormGeneratorTable
 * Tab C: Aggregated AI-Audit Statistics with charts
 * Tab D: Neutralization Mappings — FormGeneratorTable + delete
 */

import React, { useState, useCallback, useEffect, useMemo } from 'react';
import {
  ResponsiveContainer, LineChart, Line, XAxis, YAxis, CartesianGrid,
  Tooltip, BarChart, Bar, PieChart, Pie, Cell,
} from 'recharts';
import { FaDownload, FaEye, FaTrash, FaTimes } from 'react-icons/fa';
import api from '../api';
import { useLanguage } from '../providers/language/LanguageContext';
import { useUserMandates } from '../hooks/useUserMandates';
import { useConfirm } from '../hooks/useConfirm';
import { FormGeneratorTable, ColumnConfig } from '../components/FormGenerator/FormGeneratorTable';
import styles from './ComplianceAuditPage.module.css';

const CHART_COLORS = ['#1976d2', '#00897b', '#6a1b9a', '#e65100', '#5d4037', '#455a64', '#c62828', '#2e7d32'];

const _CATEGORY_COLORS: Record<string, string> = {
  security: '#c62828', gdpr: '#6a1b9a', permission: '#e65100',
  access: '#1565c0', key: '#2e7d32', data: '#00897b',
};

type TabId = 'ai-log' | 'audit-log' | 'stats' | 'neutralization';

function _tabLabel(tabId: TabId, t: (k: string) => string): string {
  switch (tabId) {
    case 'ai-log': return t('AI-Datenfluss');
    case 'audit-log': return t('Audit-Log');
    case 'stats': return t('Statistiken');
    case 'neutralization': return t('Neutralisierung');
    default: return tabId;
  }
}

// ─── Placeholder highlighting ───

const _PLACEHOLDER_RX = /\[([a-z]+)\.([a-f0-9-]{36})\]/g;

const _PH_TYPE_COLORS: Record<string, string> = {
  name: '#7c3aed', email: '#2563eb', phone: '#0891b2',
  address: '#059669', financial: '#d97706', id: '#dc2626',
  logic: '#be185d', company: '#4f46e5', product: '#7c3aed',
  location: '#059669', other: '#6b7280',
};

interface NeutMapping { id: string; originalText: string; patternType: string; }

function _renderHighlightedText(
  text: string,
  lookup: Map<string, NeutMapping>,
): React.ReactNode[] {
  const parts: React.ReactNode[] = [];
  let lastIdx = 0;
  const rx = new RegExp(_PLACEHOLDER_RX.source, 'g');
  let match: RegExpExecArray | null;

  while ((match = rx.exec(text)) !== null) {
    if (match.index > lastIdx) {
      parts.push(<span key={`t-${lastIdx}`}>{text.slice(lastIdx, match.index)}</span>);
    }
    const phType = match[1];
    const phId = match[2];
    const fullPh = match[0];
    const mapping = lookup.get(phId);
    const color = _PH_TYPE_COLORS[phType] || _PH_TYPE_COLORS.other;
    parts.push(
      <span
        key={`ph-${match.index}`}
        title={mapping ? `${mapping.originalText} (${phType})` : phType}
        style={{
          background: color + '18',
          color,
          border: `1px solid ${color}40`,
          borderRadius: 4,
          padding: '1px 4px',
          fontFamily: 'monospace',
          fontSize: '0.78rem',
          cursor: 'help',
          whiteSpace: 'nowrap',
        }}
      >
        {fullPh}
      </span>,
    );
    lastIdx = match.index + match[0].length;
  }
  if (lastIdx < text.length) {
    parts.push(<span key={`t-${lastIdx}`}>{text.slice(lastIdx)}</span>);
  }
  return parts;
}

// ─── Shared types ───

interface AuditStats {
  totalCalls: number;
  timeRangeDays: number;
  callsPerDay: Array<{ date: string; calls: number }>;
  costPerDay: Array<{ date: string; cost: number }>;
  callsByModel: Record<string, number>;
  callsByFeature: Record<string, number>;
  topUsers: Record<string, number>;
  neutralizationPercent: number;
}

interface Mandate { id: string; name?: string; label?: string; }

interface ContentModalData {
  row: any;
  contentInputFull?: string;
  contentOutputFull?: string;
  contentInputPreview?: string;
  contentOutputPreview?: string;
  neutralizationMappings: NeutMapping[];
}

const _AI_LOG_PAGE_SIZE = 50;
const _AUDIT_LOG_PAGE_SIZE = 100;
const _NEUT_PAGE_SIZE = 100;

export const ComplianceAuditPage: React.FC = () => {
  const { t } = useLanguage();
  const { fetchMandates } = useUserMandates();
  const { confirm, ConfirmDialog } = useConfirm();

  const [mandates, setMandates] = useState<Mandate[]>([]);
  const [mandatesLoading, setMandatesLoading] = useState(true);
  const [selectedMandateId, setSelectedMandateId] = useState<string | null>(null);
  const [activeTab, setActiveTab] = useState<TabId>('audit-log');

  // ── Tab A: AI-Log state ──
  const [aiEntries, setAiEntries] = useState<any[]>([]);
  const [aiPagination, setAiPagination] = useState<any>(undefined);
  const [aiLoading, setAiLoading] = useState(false);

  // ── Tab B: Audit-Log state ──
  const [auditEntries, setAuditEntries] = useState<any[]>([]);
  const [auditPagination, setAuditPagination] = useState<any>(undefined);
  const [auditLoading, setAuditLoading] = useState(false);

  // ── Tab C state ──
  const [stats, setStats] = useState<AuditStats | null>(null);
  const [statsLoading, setStatsLoading] = useState(false);
  const [statsRange, setStatsRange] = useState(30);

  // ── Tab D: Neutralization Mappings state ──
  const [neutEntries, setNeutEntries] = useState<any[]>([]);
  const [neutPagination, setNeutPagination] = useState<any>(undefined);
  const [neutLoading, setNeutLoading] = useState(false);

  // ── Content View Modal state ──
  const [contentModal, setContentModal] = useState<ContentModalData | null>(null);
  const [contentModalLoading, setContentModalLoading] = useState(false);
  const [contentModalTab, setContentModalTab] = useState<'input' | 'output'>('input');

  // ── Mandate loader ──

  useEffect(() => {
    let cancelled = false;
    (async () => {
      setMandatesLoading(true);
      try {
        const data = await fetchMandates();
        if (!cancelled) {
          const list = Array.isArray(data) ? data : [];
          setMandates(list);
          if (list.length === 1) setSelectedMandateId(list[0].id);
        }
      } catch { /* */ }
      finally { if (!cancelled) setMandatesLoading(false); }
    })();
    return () => { cancelled = true; };
  }, [fetchMandates]);

  function _mandateHeaders(): Record<string, string> {
    return selectedMandateId ? { 'X-Mandate-Id': selectedMandateId } : {};
  }

  // ── Tab A loader ──

  const _loadAiLog = useCallback(async (paginationParams?: any) => {
    if (!selectedMandateId) return;
    setAiLoading(true);
    try {
      const page = paginationParams?.page ?? 1;
      const pageSize = paginationParams?.pageSize ?? _AI_LOG_PAGE_SIZE;
      const offset = (page - 1) * pageSize;

      const params: any = { limit: pageSize, offset };
      if (paginationParams?.sort?.length) params.sort = JSON.stringify(paginationParams.sort);
      if (paginationParams?.filters && Object.keys(paginationParams.filters).length) params.filters = JSON.stringify(paginationParams.filters);
      if (paginationParams?.search) params.search = paginationParams.search;

      const { data } = await api.get('/api/audit/ai-log', {
        params,
        headers: _mandateHeaders(),
      });
      const items: any[] = data?.items ?? [];
      const totalItems = data?.totalItems ?? 0;
      setAiEntries(items);
      setAiPagination({
        currentPage: page,
        pageSize,
        totalItems,
        totalPages: Math.max(1, Math.ceil(totalItems / pageSize)),
      });
    } catch { /* */ }
    finally { setAiLoading(false); }
  }, [selectedMandateId]); // eslint-disable-line react-hooks/exhaustive-deps

  // ── Tab B loader ──

  const _loadAuditLog = useCallback(async (paginationParams?: any) => {
    if (!selectedMandateId) return;
    setAuditLoading(true);
    try {
      const page = paginationParams?.page ?? 1;
      const pageSize = paginationParams?.pageSize ?? _AUDIT_LOG_PAGE_SIZE;
      const offset = (page - 1) * pageSize;

      const params: any = { limit: pageSize, offset };
      if (paginationParams?.sort?.length) params.sort = JSON.stringify(paginationParams.sort);
      if (paginationParams?.filters && Object.keys(paginationParams.filters).length) params.filters = JSON.stringify(paginationParams.filters);
      if (paginationParams?.search) params.search = paginationParams.search;

      const { data } = await api.get('/api/audit/log', {
        params,
        headers: _mandateHeaders(),
      });
      const items: any[] = data?.items ?? [];
      const totalItems = data?.totalItems ?? items.length;
      setAuditEntries(items);
      setAuditPagination({
        currentPage: page,
        pageSize,
        totalItems,
        totalPages: Math.max(1, Math.ceil(totalItems / pageSize)),
      });
    } catch { /* */ }
    finally { setAuditLoading(false); }
  }, [selectedMandateId]); // eslint-disable-line react-hooks/exhaustive-deps

  // ── Tab C loader ──

  const _loadStats = useCallback(async (days = 30) => {
    if (!selectedMandateId) return;
    setStatsLoading(true);
    try {
      const { data } = await api.get('/api/audit/stats', {
        params: { timeRange: days },
        headers: _mandateHeaders(),
      });
      setStats(data ?? null);
    } catch { /* */ }
    finally { setStatsLoading(false); }
  }, [selectedMandateId]); // eslint-disable-line react-hooks/exhaustive-deps

  // ── Tab D loader ──

  const _loadNeutMappings = useCallback(async (paginationParams?: any) => {
    if (!selectedMandateId) return;
    setNeutLoading(true);
    try {
      const page = paginationParams?.page ?? 1;
      const pageSize = paginationParams?.pageSize ?? _NEUT_PAGE_SIZE;
      const offset = (page - 1) * pageSize;

      const neutParams: any = { limit: pageSize, offset };
      if (paginationParams?.sort?.length) neutParams.sort = JSON.stringify(paginationParams.sort);
      if (paginationParams?.filters && Object.keys(paginationParams.filters).length) neutParams.filters = JSON.stringify(paginationParams.filters);
      if (paginationParams?.search) neutParams.search = paginationParams.search;

      const { data } = await api.get('/api/audit/neutralization-mappings', {
        params: neutParams,
        headers: _mandateHeaders(),
      });
      const items: any[] = data?.items ?? [];
      const totalItems = data?.totalItems ?? 0;
      setNeutEntries(items);
      setNeutPagination({
        currentPage: page,
        pageSize,
        totalItems,
        totalPages: Math.max(1, Math.ceil(totalItems / pageSize)),
      });
    } catch { /* */ }
    finally { setNeutLoading(false); }
  }, [selectedMandateId]); // eslint-disable-line react-hooks/exhaustive-deps

  const _handleDeleteMapping = useCallback(async (row: any) => {
    if (!selectedMandateId || !row?.id) return;
    const ok = await confirm(
      t('Soll diese Zuordnung wirklich gelöscht werden?'),
      { confirmLabel: t('Löschen'), variant: 'danger' },
    );
    if (!ok) return;
    try {
      await api.delete(`/api/audit/neutralization-mappings/${row.id}`, {
        headers: _mandateHeaders(),
      });
      void _loadNeutMappings();
    } catch (err) {
      console.error('Delete mapping failed:', err);
    }
  }, [selectedMandateId, _loadNeutMappings, confirm, t]); // eslint-disable-line react-hooks/exhaustive-deps

  const _handleDeleteMappingsBatch = useCallback(async (rows: any[]) => {
    if (!selectedMandateId || rows.length === 0) return;
    const ok = await confirm(
      t('{n} Zuordnungen wirklich löschen?', { n: String(rows.length) }),
      { confirmLabel: t('Alle löschen'), variant: 'danger' },
    );
    if (!ok) return;
    try {
      await Promise.all(
        rows.map(row => api.delete(`/api/audit/neutralization-mappings/${row.id}`, {
          headers: _mandateHeaders(),
        }))
      );
      void _loadNeutMappings();
    } catch (err) {
      console.error('Batch delete failed:', err);
    }
  }, [selectedMandateId, _loadNeutMappings, confirm, t]); // eslint-disable-line react-hooks/exhaustive-deps

  // ── Auto-load on tab / mandate change ──

  useEffect(() => {
    if (!selectedMandateId) return;
    if (activeTab === 'ai-log') void _loadAiLog();
    else if (activeTab === 'audit-log') void _loadAuditLog();
    else if (activeTab === 'stats') void _loadStats(statsRange);
    else if (activeTab === 'neutralization') void _loadNeutMappings();
  }, [activeTab, selectedMandateId]); // eslint-disable-line react-hooks/exhaustive-deps

  // ── Content view handler (modal) ──

  const _handleContentView = useCallback(async (row: any) => {
    if (!selectedMandateId || !row?.id) return;
    setContentModalLoading(true);
    setContentModalTab('input');
    setContentModal({ row, neutralizationMappings: [] });
    try {
      const { data } = await api.get(`/api/audit/ai-log/${row.id}/content`, {
        headers: _mandateHeaders(),
      });
      setContentModal({
        row,
        contentInputFull: data?.contentInputFull,
        contentOutputFull: data?.contentOutputFull,
        contentInputPreview: data?.contentInputPreview,
        contentOutputPreview: data?.contentOutputPreview,
        neutralizationMappings: data?.neutralizationMappings ?? [],
      });
    } catch (err) {
      console.error('Content load failed:', err);
    } finally {
      setContentModalLoading(false);
    }
  }, [selectedMandateId]); // eslint-disable-line react-hooks/exhaustive-deps

  // ── Content download handler ──

  const _handleContentDownload = useCallback(async (row: any) => {
    if (!selectedMandateId || !row?.id) return;
    try {
      const { data } = await api.get(`/api/audit/ai-log/${row.id}/content`, {
        headers: _mandateHeaders(),
      });
      const ts = row.timestamp ? new Date(row.timestamp * 1000).toISOString() : '–';
      const text = [
        `=== AI-Audit-Eintrag: ${row.id} ===`,
        `Zeitpunkt: ${ts}`,
        `Benutzer: ${row.username || row.userId || '–'}`,
        `Provider: ${row.aiProvider || '–'}`,
        `Modell: ${row.aiModel || '–'}`,
        `Typ: ${row.operationType || '–'}`,
        `Neutralisierung: ${row.neutralizationActive ? 'aktiv' : 'inaktiv'}`,
        `Status: ${row.success ? 'OK' : 'Fehler'}`,
        '',
        '=== Input (was an AI gesendet wurde) ===',
        data?.contentInputFull || data?.contentInputPreview || '(kein Input gespeichert)',
        '',
        '=== Output (AI-Antwort) ===',
        data?.contentOutputFull || data?.contentOutputPreview || '(kein Output gespeichert)',
      ].join('\n');

      const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `ai-audit-${row.id.slice(0, 8)}.txt`;
      a.click();
      URL.revokeObjectURL(url);
    } catch (err) {
      console.error('Content download failed:', err);
    }
  }, [selectedMandateId]); // eslint-disable-line react-hooks/exhaustive-deps

  // ── Mapping lookup for modal ──

  const _modalMappingLookup = useMemo(() => {
    const map = new Map<string, NeutMapping>();
    if (contentModal?.neutralizationMappings) {
      for (const m of contentModal.neutralizationMappings) {
        map.set(m.id, m);
      }
    }
    return map;
  }, [contentModal?.neutralizationMappings]);

  // ── Column definitions ──

  const aiLogColumns: ColumnConfig[] = useMemo(() => [
    { key: 'timestamp', label: t('Zeitpunkt'), type: 'timestamp' as any, sortable: true, width: 160 },
    {
      key: 'username', label: t('Benutzer'), type: 'text' as any, sortable: true, searchable: true, width: 140,
      formatter: (val: any, row: any) => val || (row?.userId ? row.userId.slice(0, 8) : '–'),
    },
    {
      key: 'instanceLabel', label: t('Feature-Instanz'), type: 'text' as any, sortable: true, filterable: true, width: 160,
      formatter: (val: any, row: any) => val || row?.featureCode || '–',
    },
    { key: 'aiModel', label: t('AI-Modell'), type: 'text' as any, sortable: true, filterable: true, width: 160 },
    {
      key: 'aiProvider', label: t('Provider / Typ'), type: 'text' as any, sortable: true, filterable: true, width: 140,
      formatter: (val: any, row: any) => {
        const provider = val || '–';
        const op = row?.operationType;
        return op ? `${provider} · ${op}` : provider;
      },
    },
    {
      key: 'priceCHF', label: t('Kosten (CHF)'), type: 'number' as any, sortable: true, width: 110,
      formatter: (val: any) => val != null ? Number(val).toFixed(4) : '–',
    },
    {
      key: 'neutralizationActive', label: t('Neutralisierung'), type: 'text' as any, sortable: true, width: 100,
      formatter: (val: any) => val ? '✓' : '–',
    },
    {
      key: 'success', label: t('Status'), type: 'text' as any, sortable: true, filterable: true, width: 80,
      formatter: (val: any) => val ? t('OK') : t('Fehler'),
      cellClassName: (val: any) => val ? styles.statusOk : styles.statusError,
    },
  ], [t]);

  const auditLogColumns: ColumnConfig[] = useMemo(() => [
    { key: 'timestamp', label: t('Zeitpunkt'), type: 'timestamp' as any, sortable: true, width: 160 },
    {
      key: 'username', label: t('Benutzer'), type: 'text' as any, sortable: true, searchable: true, width: 140,
      formatter: (val: any, row: any) => val || (row?.userId ? row.userId.slice(0, 8) : '–'),
    },
    {
      key: 'category', label: t('Kategorie'), type: 'text' as any, sortable: true, filterable: true, width: 110,
      cellClassName: (val: any) => {
        const color = _CATEGORY_COLORS[val as string];
        return color ? styles[`cat_${val}`] || '' : '';
      },
      formatter: (val: any) => val || '–',
    },
    { key: 'action', label: t('Aktion'), type: 'text' as any, sortable: true, filterable: true, searchable: true, width: 140 },
    { key: 'resourceType', label: t('Ressource'), type: 'text' as any, sortable: true, filterable: true, width: 120 },
    { key: 'details', label: t('Details'), type: 'text' as any, searchable: true, width: 250 },
    {
      key: 'success', label: t('Status'), type: 'text' as any, sortable: true, width: 70,
      formatter: (val: any) => val ? '✓' : '✗',
      cellClassName: (val: any) => val ? styles.statusOk : styles.statusError,
    },
    { key: 'ipAddress', label: t('IP'), type: 'text' as any, width: 120 },
  ], [t]);

  const neutColumns: ColumnConfig[] = useMemo(() => [
    { key: 'placeholder', label: t('Platzhalter'), type: 'text' as any, sortable: true, searchable: true, width: 220 },
    { key: 'originalText', label: t('Originaltext'), type: 'text' as any, sortable: true, searchable: true, width: 240 },
    { key: 'patternType', label: t('Kategorie'), type: 'text' as any, sortable: true, filterable: true, width: 120 },
    {
      key: 'username', label: t('Benutzer'), type: 'text' as any, sortable: true, filterable: true, width: 140,
      formatter: (val: any, row: any) => val || (row?.userId ? String(row.userId).slice(0, 8) + '…' : '–'),
    },
    {
      key: 'instanceLabel', label: t('Feature-Instanz'), type: 'text' as any, sortable: true, filterable: true, width: 160,
      formatter: (val: any, row: any) => val || (row?.featureInstanceId ? String(row.featureInstanceId).slice(0, 8) + '…' : '–'),
    },
    {
      key: 'fileId', label: t('Datei'), type: 'text' as any, sortable: true, width: 140,
      formatter: (val: any) => val ? String(val).slice(0, 8) + '…' : '–',
    },
  ], [t]);

  // ── fetchFilterValues for autofilter dropdowns ──

  const _makeFetchFilterValues = useCallback(
    (endpoint: string) => async (columnKey: string, crossFilters?: Record<string, any>) => {
      if (!selectedMandateId) return [];
      try {
        const params: any = { mode: 'filterValues', column: columnKey };
        if (crossFilters && Object.keys(crossFilters).length) {
          params.filters = JSON.stringify(crossFilters);
        }
        const { data } = await api.get(endpoint, { params, headers: _mandateHeaders() });
        return Array.isArray(data) ? data : [];
      } catch { return []; }
    },
    [selectedMandateId], // eslint-disable-line react-hooks/exhaustive-deps
  );

  // ── hookData for FormGeneratorTable ──

  const aiLogHookData = useMemo(() => ({
    refetch: _loadAiLog,
    pagination: aiPagination,
    fetchFilterValues: _makeFetchFilterValues('/api/audit/ai-log'),
  }), [_loadAiLog, aiPagination, _makeFetchFilterValues]);

  const auditLogHookData = useMemo(() => ({
    refetch: _loadAuditLog,
    pagination: auditPagination,
    fetchFilterValues: _makeFetchFilterValues('/api/audit/log'),
  }), [_loadAuditLog, auditPagination, _makeFetchFilterValues]);

  const neutHookData = useMemo(() => ({
    refetch: _loadNeutMappings,
    pagination: neutPagination,
    fetchFilterValues: _makeFetchFilterValues('/api/audit/neutralization-mappings'),
  }), [_loadNeutMappings, neutPagination, _makeFetchFilterValues]);

  // ── Render ──

  const _tabs: TabId[] = ['audit-log', 'ai-log', 'neutralization', 'stats'];

  return (
    <div className={styles.wrap}>
      <h2 className={styles.pageTitle}>{t('Compliance & AI-Audit')}</h2>
      <p className={styles.pageDesc}>
        {t('Transparente Übersicht aller AI-Datenflüsse und Sicherheitsereignisse Ihres Mandanten.')}
      </p>

      {/* Mandate selector */}
      <div className={styles.mandateSelector}>
        <label className={styles.mandateLabel}>{t('Mandant auswählen')}</label>
        <select
          className={styles.mandateSelect}
          value={selectedMandateId || ''}
          onChange={e => setSelectedMandateId(e.target.value || null)}
          disabled={mandatesLoading}
        >
          <option value="">{mandatesLoading ? t('Lade…') : t('— Mandant wählen —')}</option>
          {mandates.map(m => (
            <option key={m.id} value={m.id}>{m.label || m.name || m.id}</option>
          ))}
        </select>
      </div>

      {!selectedMandateId ? (
        <p className={styles.emptyText}>{t('Bitte wählen Sie einen Mandanten aus.')}</p>
      ) : (
      <>
      {/* Tab bar */}
      <div className={styles.tabBar}>
        {_tabs.map(tab => (
          <button
            key={tab}
            className={`${styles.tab} ${activeTab === tab ? styles.tabActive : ''}`}
            onClick={() => setActiveTab(tab)}
          >
            {_tabLabel(tab, t)}
          </button>
        ))}
      </div>

      {/* ── Tab A: AI Data-Flow Log ── */}
      {activeTab === 'ai-log' && (
        <div className={styles.tabContent}>
          <FormGeneratorTable
            key={`ai-log-${selectedMandateId}`}
            data={aiEntries}
            columns={aiLogColumns}
            loading={aiLoading}
            pagination={true}
            pageSize={_AI_LOG_PAGE_SIZE}
            sortable={true}
            filterable={true}
            searchable={true}
            selectable={false}
            emptyMessage={t('Keine AI-Audit-Einträge vorhanden.')}
            onRefresh={_loadAiLog}
            hookData={aiLogHookData}
            customActions={[
              {
                id: 'viewContent',
                title: t('Input/Output anzeigen'),
                icon: <FaEye />,
                onClick: _handleContentView,
              },
              {
                id: 'downloadContent',
                title: t('Input/Output herunterladen'),
                icon: <FaDownload />,
                onClick: _handleContentDownload,
              },
            ]}
          />
        </div>
      )}

      {/* ── Tab B: Audit Log ── */}
      {activeTab === 'audit-log' && (
        <div className={styles.tabContent}>
          <FormGeneratorTable
            key={`audit-log-${selectedMandateId}`}
            data={auditEntries}
            columns={auditLogColumns}
            loading={auditLoading}
            pagination={true}
            pageSize={_AUDIT_LOG_PAGE_SIZE}
            sortable={true}
            filterable={true}
            searchable={true}
            selectable={false}
            emptyMessage={t('Keine Audit-Einträge vorhanden.')}
            onRefresh={_loadAuditLog}
            hookData={auditLogHookData}
          />
        </div>
      )}

      {/* ── Tab C: Statistics ── */}
      {activeTab === 'stats' && (
        <div className={styles.tabContentScrollable}>
          <div className={styles.statsControls}>
            {[7, 30, 90].map(d => (
              <button
                key={d}
                className={`${styles.rangeBtn} ${statsRange === d ? styles.rangeBtnActive : ''}`}
                onClick={() => { setStatsRange(d); void _loadStats(d); }}
              >
                {t('{n} Tage', { n: String(d) })}
              </button>
            ))}
          </div>

          {statsLoading ? (
            <p className={styles.loadingText}>{t('Lade Statistiken…')}</p>
          ) : !stats ? (
            <p className={styles.emptyText}>{t('Keine Daten verfügbar.')}</p>
          ) : (
            <>
              {/* KPIs */}
              <div className={styles.kpiGrid}>
                <div className={styles.kpiCard}>
                  <p className={styles.kpiValue}>{stats.totalCalls}</p>
                  <p className={styles.kpiLabel}>{t('AI-Aufrufe')}</p>
                </div>
                <div className={styles.kpiCard}>
                  <p className={styles.kpiValue}>{stats.neutralizationPercent}%</p>
                  <p className={styles.kpiLabel}>{t('Neutralisierungsquote')}</p>
                </div>
                <div className={styles.kpiCard}>
                  <p className={styles.kpiValue}>{Object.keys(stats.callsByModel).length}</p>
                  <p className={styles.kpiLabel}>{t('Genutzte Modelle')}</p>
                </div>
                <div className={styles.kpiCard}>
                  <p className={styles.kpiValue}>
                    {stats.costPerDay.reduce((s, d) => s + d.cost, 0).toFixed(2)}
                  </p>
                  <p className={styles.kpiLabel}>{t('Gesamtkosten (CHF)')}</p>
                </div>
              </div>

              {/* Charts row 1: Calls/Day + Cost/Day */}
              <div className={styles.chartRow}>
                <div className={styles.chartBlock}>
                  <h3 className={styles.chartTitle}>{t('AI-Aufrufe pro Tag')}</h3>
                  {stats.callsPerDay.length === 0 ? (
                    <p className={styles.meta}>{t('Keine Daten')}</p>
                  ) : (
                    <ResponsiveContainer width="100%" height={220}>
                      <LineChart data={stats.callsPerDay}>
                        <CartesianGrid strokeDasharray="3 3" />
                        <XAxis dataKey="date" tick={{ fontSize: 10 }} />
                        <YAxis allowDecimals={false} tick={{ fontSize: 10 }} />
                        <Tooltip />
                        <Line type="monotone" dataKey="calls" name={t('Aufrufe')} stroke="#1976d2" dot={false} strokeWidth={2} />
                      </LineChart>
                    </ResponsiveContainer>
                  )}
                </div>
                <div className={styles.chartBlock}>
                  <h3 className={styles.chartTitle}>{t('Kosten-Verlauf (CHF)')}</h3>
                  {stats.costPerDay.length === 0 ? (
                    <p className={styles.meta}>{t('Keine Daten')}</p>
                  ) : (
                    <ResponsiveContainer width="100%" height={220}>
                      <LineChart data={stats.costPerDay}>
                        <CartesianGrid strokeDasharray="3 3" />
                        <XAxis dataKey="date" tick={{ fontSize: 10 }} />
                        <YAxis tick={{ fontSize: 10 }} />
                        <Tooltip />
                        <Line type="monotone" dataKey="cost" name={t('CHF')} stroke="#e65100" dot={false} strokeWidth={2} />
                      </LineChart>
                    </ResponsiveContainer>
                  )}
                </div>
              </div>

              {/* Charts row 2: By Model (pie) + By Feature (bar) */}
              <div className={styles.chartRow}>
                <div className={styles.chartBlock}>
                  <h3 className={styles.chartTitle}>{t('AI-Aufrufe nach Modell')}</h3>
                  {Object.keys(stats.callsByModel).length === 0 ? (
                    <p className={styles.meta}>{t('Keine Daten')}</p>
                  ) : (
                    <ResponsiveContainer width="100%" height={240}>
                      <PieChart>
                        <Pie
                          data={Object.entries(stats.callsByModel).map(([name, value]) => ({ name, value }))}
                          dataKey="value" nameKey="name"
                          cx="50%" cy="50%" outerRadius={80}
                          label={({ name, percent }) => `${name} ${((percent ?? 0) * 100).toFixed(0)}%`}
                        >
                          {Object.keys(stats.callsByModel).map((_, i) => (
                            <Cell key={i} fill={CHART_COLORS[i % CHART_COLORS.length]} />
                          ))}
                        </Pie>
                        <Tooltip />
                      </PieChart>
                    </ResponsiveContainer>
                  )}
                </div>
                <div className={styles.chartBlock}>
                  <h3 className={styles.chartTitle}>{t('AI-Aufrufe nach Feature')}</h3>
                  {Object.keys(stats.callsByFeature).length === 0 ? (
                    <p className={styles.meta}>{t('Keine Daten')}</p>
                  ) : (
                    <ResponsiveContainer width="100%" height={240}>
                      <BarChart data={Object.entries(stats.callsByFeature).map(([name, value]) => ({ name, value }))}>
                        <CartesianGrid strokeDasharray="3 3" />
                        <XAxis dataKey="name" tick={{ fontSize: 10 }} />
                        <YAxis allowDecimals={false} tick={{ fontSize: 10 }} />
                        <Tooltip />
                        <Bar dataKey="value" name={t('Aufrufe')} fill="#00897b" radius={[4, 4, 0, 0]} />
                      </BarChart>
                    </ResponsiveContainer>
                  )}
                </div>
              </div>

              {/* Top Users */}
              {Object.keys(stats.topUsers).length > 0 && (
                <div className={styles.chartBlock}>
                  <h3 className={styles.chartTitle}>{t('Top-Nutzer nach AI-Aufrufen')}</h3>
                  <ResponsiveContainer width="100%" height={200}>
                    <BarChart
                      data={Object.entries(stats.topUsers).map(([name, value]) => ({ name, value }))}
                      layout="vertical" margin={{ left: 8, right: 16 }}
                    >
                      <CartesianGrid strokeDasharray="3 3" />
                      <XAxis type="number" allowDecimals={false} />
                      <YAxis type="category" dataKey="name" width={140} tick={{ fontSize: 10 }} />
                      <Tooltip />
                      <Bar dataKey="value" name={t('Aufrufe')} fill="#6a1b9a" radius={[0, 4, 4, 0]} />
                    </BarChart>
                  </ResponsiveContainer>
                </div>
              )}
            </>
          )}
        </div>
      )}

      {/* ── Tab D: Neutralization Mappings ── */}
      {activeTab === 'neutralization' && (
        <div className={styles.tabContent}>
          <FormGeneratorTable
            key={`neut-${selectedMandateId}`}
            data={neutEntries}
            columns={neutColumns}
            loading={neutLoading}
            pagination={true}
            pageSize={_NEUT_PAGE_SIZE}
            sortable={true}
            filterable={true}
            searchable={true}
            selectable={true}
            emptyMessage={t('Keine Neutralisierungs-Zuordnungen vorhanden.')}
            onRefresh={_loadNeutMappings}
            hookData={neutHookData}
            batchActions={[
              {
                label: t('Ausgewählte löschen'),
                onClick: _handleDeleteMappingsBatch,
              },
            ]}
            customActions={[
              {
                id: 'deleteMapping',
                title: t('Zuordnung löschen'),
                icon: <FaTrash />,
                onClick: _handleDeleteMapping,
              },
            ]}
          />
        </div>
      )}
      </>
      )}

      {/* ── Content View Modal ── */}
      {contentModal && (
        <div className={styles.modalOverlay}>
          <div className={styles.modalContainer}>
            <div className={styles.modalHeader}>
              <h3 className={styles.modalTitle}>{t('AI-Audit Inhalt')}</h3>
              <div className={styles.modalMeta}>
                {contentModal.row?.username || contentModal.row?.userId?.slice(0, 8) || '–'}
                {' · '}
                {contentModal.row?.aiModel || '–'}
                {' · '}
                {contentModal.row?.timestamp
                  ? new Date(contentModal.row.timestamp * 1000).toLocaleString()
                  : '–'}
              </div>
              <button
                className={styles.modalClose}
                onClick={() => setContentModal(null)}
                title={t('Schliessen')}
              >
                <FaTimes />
              </button>
            </div>

            {contentModal.neutralizationMappings.length > 0 && (
              <div className={styles.modalMappingBar}>
                <span className={styles.modalMappingLabel}>
                  {t('{n} Platzhalter aufgelöst', { n: String(contentModal.neutralizationMappings.length) })}
                </span>
                <span className={styles.modalMappingHint}>
                  {t('Hover über markierte Platzhalter für Originaltext')}
                </span>
              </div>
            )}

            <div className={styles.modalTabBar}>
              <button
                className={`${styles.modalTab} ${contentModalTab === 'input' ? styles.modalTabActive : ''}`}
                onClick={() => setContentModalTab('input')}
              >
                {t('Input')}
              </button>
              <button
                className={`${styles.modalTab} ${contentModalTab === 'output' ? styles.modalTabActive : ''}`}
                onClick={() => setContentModalTab('output')}
              >
                {t('Output')}
              </button>
            </div>

            <div className={styles.modalBody}>
              {contentModalLoading ? (
                <p className={styles.loadingText}>{t('Lade Inhalt…')}</p>
              ) : (
                <div className={styles.modalTextContent}>
                  {contentModalTab === 'input' ? (
                    (() => {
                      const text = contentModal.contentInputFull
                        || contentModal.contentInputPreview
                        || t('(kein Input gespeichert)');
                      return _modalMappingLookup.size > 0
                        ? _renderHighlightedText(text, _modalMappingLookup)
                        : text;
                    })()
                  ) : (
                    (() => {
                      const text = contentModal.contentOutputFull
                        || contentModal.contentOutputPreview
                        || t('(kein Output gespeichert)');
                      return _modalMappingLookup.size > 0
                        ? _renderHighlightedText(text, _modalMappingLookup)
                        : text;
                    })()
                  )}
                </div>
              )}
            </div>
          </div>
        </div>
      )}

      <ConfirmDialog />
    </div>
  );
};
