// Copyright (c) 2026 PowerOn AG
// All rights reserved.
/**
 * RagInventoryPage — Global RAG knowledge store management.
 *
 * Accessible via Start > Nutzung > RAG-Inventar.
 * Context selector top-right (same pattern as BillingDataView / Statistiken):
 *   Dropdown: "Meine Verbindungen" | "Mandant: XY" | "Plattform (alle)"
 *   Checkbox: "nur meine Daten"
 */

import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useLanguage } from '../providers/language/LanguageContext';
import { useApiRequest } from '../hooks/useApi';
import { useConfirm } from '../hooks/useConfirm';
import type { RagInventoryDto, RagConnectionDto, RagDataSourceDto, RagFeatureInstanceDto } from '../api/connectionApi';
import api from '../api';
import { FaDatabase, FaStop, FaSync, FaToggleOn, FaToggleOff, FaRedo, FaExclamationTriangle, FaCheckCircle, FaSlidersH, FaCubes } from 'react-icons/fa';
import { mandateDisplayLabel } from '../utils/mandateDisplayUtils';
import { DataSourceSettingsModal } from '../components/UnifiedDataBar/DataSourceSettingsModal';
import { StackLayout } from '../components/Layout/StackLayout';
import { Panel } from '../components/Layout/Panel';
import styles from './RagInventoryPage.module.css';

export const RagInventoryPage: React.FC = () => {
  const { t } = useLanguage();
  const { request } = useApiRequest();
  const { confirm, ConfirmDialog } = useConfirm();
  const [searchParams, setSearchParams] = useSearchParams();

  const [mandates, setMandates] = useState<any[]>([]);
  const [mandatesLoading, setMandatesLoading] = useState(true);
  const selectedScope = searchParams.get('context') || 'personal';
  const onlyMyData = searchParams.get('onlyMine') === 'true';

  const [inventory, setInventory] = useState<RagInventoryDto | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const [settingsModal, setSettingsModal] = useState<{
    dataSourceId?: string;
    connectionId?: string;
    title: string;
    initialKnowledgeIngestionEnabled?: boolean;
  } | null>(null);

  const _openSettingsForConnection = useCallback((conn: RagConnectionDto) => {
    const activeDs = (conn.dataSources || []).find(ds => ds.ragIndexEnabled) || (conn.dataSources || [])[0];
    setSettingsModal({
      dataSourceId: activeDs?.id,
      connectionId: conn.id,
      title: `${conn.authority} · ${conn.externalEmail || conn.id}`,
      initialKnowledgeIngestionEnabled: conn.knowledgeIngestionEnabled,
    });
  }, []);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      setMandatesLoading(true);
      try {
        const data = await request({ url: '/api/rag/inventory/my-mandates', method: 'get' });
        if (!cancelled) {
          const list = Array.isArray(data) ? data : [];
          setMandates(list);
          if (list.length === 1 && selectedScope === 'personal') {
            setSearchParams((prev) => {
              const next = new URLSearchParams(prev);
              next.set('context', list[0].id);
              return next;
            }, { replace: true });
          }
        }
      } catch {}
      finally { if (!cancelled) setMandatesLoading(false); }
    })();
    return () => { cancelled = true; };
  }, [request, selectedScope, setSearchParams]);

  const _handleScopeChange = useCallback((value: string) => {
    setSearchParams((prev) => {
      const next = new URLSearchParams(prev);
      if (value === 'personal') next.delete('context');
      else next.set('context', value);
      return next;
    }, { replace: true });
  }, [setSearchParams]);

  const _handleOnlyMyDataChange = useCallback((checked: boolean) => {
    setSearchParams((prev) => {
      const next = new URLSearchParams(prev);
      if (checked) next.set('onlyMine', 'true');
      else next.delete('onlyMine');
      return next;
    }, { replace: true });
  }, [setSearchParams]);

  const _apiEndpoint = useMemo(() => {
    if (selectedScope === 'personal') return '/api/rag/inventory/me';
    if (selectedScope === 'platform') return '/api/rag/inventory/platform';
    return '/api/rag/inventory/mandate';
  }, [selectedScope]);

  const _fetchInventory = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const params: Record<string, string> = {};
      if (onlyMyData) params.onlyMine = 'true';
      const isMandateScope = selectedScope !== 'personal' && selectedScope !== 'platform';
      const headers: Record<string, string> = {};
      if (isMandateScope) {
        headers['X-Mandate-Id'] = selectedScope;
      }
      const data = await request({ url: _apiEndpoint, method: 'get', params, additionalConfig: { headers } });
      setInventory(data);
    } catch (err: any) {
      if (err?.message?.includes('403')) {
        setError(t('Keine Berechtigung für diese Sicht.'));
      } else {
        setError(err?.message || t('Fehler beim Laden'));
      }
      setInventory(null);
    } finally {
      setLoading(false);
    }
  }, [request, _apiEndpoint, selectedScope, onlyMyData, t]);

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

  const _hasActiveJobs = !!(
    inventory?.connections?.some(c => (c.runningJobs?.length || 0) > 0) ||
    inventory?.featureInstances?.some(fi => (fi.runningJobs?.length || 0) > 0)
  );

  useEffect(() => {
    if (pollRef.current) clearInterval(pollRef.current);
    // Fast poll (5s) while a sync is in flight so the user gets a snappy
    // success/error confirmation; slow poll (60s) at rest to keep the DB
    // load low. Visibility check skips polling for backgrounded tabs.
    const intervalMs = _hasActiveJobs ? 5000 : 60000;
    pollRef.current = setInterval(() => {
      if (document.visibilityState === 'visible') _fetchInventory();
    }, intervalMs);
    return () => { if (pollRef.current) clearInterval(pollRef.current); };
  }, [_fetchInventory, _hasActiveJobs]);

  const _handleStop = async (connectionId: string) => {
    try {
      await request({ url: `/api/connections/${connectionId}/knowledge-stop`, method: 'post' });
      _fetchInventory();
    } catch {}
  };

  const _handleReindex = async (connectionId: string) => {
    try {
      await request({ url: `/api/rag/inventory/reindex/${connectionId}`, method: 'post' });
      _fetchInventory();
    } catch {}
  };

  const _handleReindexFeature = async (workspaceInstanceId: string) => {
    try {
      await request({ url: `/api/rag/inventory/reindex-feature/${workspaceInstanceId}`, method: 'post' });
      _fetchInventory();
    } catch {}
  };

  const _handleDsRagToggle = async (connectionId: string, ds: RagDataSourceDto) => {
    const nodeKey = `ds|${connectionId}|${ds.sourceType}|${ds.path}`;
    const newValue = !ds.ragIndexEnabled;
    try {
      await api.post(`/api/udb/node/${encodeURIComponent(nodeKey)}/flag/ragIndexEnabled`, { value: newValue });
      _fetchInventory();
    } catch {}
  };

  const _handleConsentToggle = async (connectionId: string, currentEnabled: boolean) => {
    if (currentEnabled) {
      const ok = await confirm(t('Alle indexierten Inhalte dieser Verbindung werden entfernt. Fortfahren?'), { variant: 'danger', confirmLabel: t('Fortfahren') });
      if (!ok) return;
    }
    try {
      await request({
        url: `/api/connections/${connectionId}/knowledge-consent`,
        method: 'patch',
        data: { enabled: !currentEnabled },
      });
      _fetchInventory();
    } catch {}
  };

  const _formatRelative = useCallback((finishedAt: number | null | undefined): string => {
    if (!finishedAt) return '';
    const nowSec = Date.now() / 1000;
    const diff = Math.max(0, nowSec - finishedAt);
    if (diff < 45) return t('gerade eben');
    if (diff < 3600) return t('vor {n} Min', { n: Math.floor(diff / 60) });
    if (diff < 86400) return t('vor {n} Std', { n: Math.floor(diff / 3600) });
    return t('vor {n} Tag(en)', { n: Math.floor(diff / 86400) });
  }, [t]);

  const _formatDuration = useCallback((ms: number | undefined): string => {
    if (!ms || ms <= 0) return '';
    if (ms < 1000) return `${ms}ms`;
    if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
    return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`;
  }, []);

  /** Render the budget value next to its name. Bytes get MB units so the user
   *  immediately recognises the 200 MB default; everything else stays raw. */
  const _formatLimit = useCallback((name: string, budget: number | undefined, bytesProcessed: number | undefined): string => {
    if (budget == null) return name;
    if (name === 'maxBytes') {
      const mb = Math.round(budget / 1024 / 1024);
      const procMb = bytesProcessed != null ? ` (${(bytesProcessed / 1024 / 1024).toFixed(0)} MB ${t('verarbeitet')})` : '';
      return `${name}=${mb} MB${procMb}`;
    }
    if (name === 'maxFileSize') {
      return `${name}=${Math.round(budget / 1024 / 1024)} MB`;
    }
    return `${name}=${budget}`;
  }, [t]);

  const scopeOptions = useMemo(() => {
    const opts: { value: string; label: string }[] = [
      { value: 'personal', label: t('Meine Verbindungen') },
    ];
    for (const m of mandates) {
      opts.push({ value: m.id, label: t('Mandant: {name}', { name: mandateDisplayLabel(m) }) });
    }
    opts.push({ value: 'platform', label: t('Plattform (alle)') });
    return opts;
  }, [mandates, t]);

  return (
    <StackLayout variant="scroll">
      <ConfirmDialog />
      <StackLayout.Header>
        <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: '1rem', flexWrap: 'wrap' }}>
          <div style={{ display: 'flex', alignItems: 'flex-start', gap: '0.75rem' }}>
            <FaDatabase className={styles.headerIcon} />
            <div>
              <h1 style={{ fontSize: '1.5rem', fontWeight: 600, margin: 0 }}>{t('RAG-Inventar')}</h1>
              <p className={styles.pageDesc}>
                {t('Übersicht und Steuerung der indexierten Wissensdaten.')}
              </p>
            </div>
          </div>
        </div>
      </StackLayout.Header>
      <StackLayout.Body>
        <Panel variant="toolbar" title={t('Filter')} id="rag-inventory-toolbar">
          <div className={styles.headerRight} style={{ marginLeft: 0 }}>
            <div className={styles.filterGroup}>
              <label className={styles.filterLabel}>{t('Kontext:')}</label>
              <select
                className={styles.scopeSelect}
                value={selectedScope}
                onChange={e => _handleScopeChange(e.target.value)}
                disabled={mandatesLoading}
              >
                {scopeOptions.map(opt => (
                  <option key={opt.value} value={opt.value}>{opt.label}</option>
                ))}
              </select>
            </div>
            <label className={styles.checkboxLabel}>
              <input
                type="checkbox"
                checked={onlyMyData}
                onChange={e => _handleOnlyMyDataChange(e.target.checked)}
              />
              {t('nur meine Daten')}
            </label>
          </div>
        </Panel>

        {loading && !inventory && (
          <Panel variant="card" title={t('Laden...')} id="rag-inventory-loading">
            <div className={styles.loading}>{t('Laden...')}</div>
          </Panel>
        )}
        {error && (
          <Panel variant="card" title={t('Fehler')} id="rag-inventory-error">
            <div className={styles.error}>{error}</div>
          </Panel>
        )}

        {inventory && (
          <>
            <Panel variant="card" title={t('Übersicht')} id="rag-inventory-totals">
              <div className={styles.totals}>
                <span className={styles.totalLabel}>{t('Total Dateien')}:</span>
                <strong className={styles.totalValue}>{inventory.totals?.files ?? 0}</strong>
                <span className={styles.totalLabel} title={t('Embedding-Fragmente (~400 Tokens), die der RAG-Retrieval trifft')}>{t('Total Chunks')}:</span>
                <strong className={styles.totalValue}>{inventory.totals?.chunks ?? 0}</strong>
                {inventory.totals?.bytes != null && inventory.totals.bytes > 0 && (
                  <span className={styles.totalBytes}>{(inventory.totals.bytes / 1024 / 1024).toFixed(1)} MB</span>
                )}
              </div>
            </Panel>

            {(inventory.connections || []).map((conn: RagConnectionDto) => (
              <Panel key={conn.id} variant="card" title={t('Datenverbindung')} id={`rag-connection-${conn.id}`}>
                <div className={styles.connectionCard} style={{ border: 'none', padding: 0, background: 'transparent' }}>
              <div className={styles.connectionHeader}>
                <span className={styles.authority}>{conn.authority}</span>
                <span className={styles.email}>{conn.externalEmail}</span>
                {(conn.totalFiles > 0 || conn.totalChunks > 0) && (
                  <span
                    className={styles.connChunks}
                    title={t('Embedding-Fragmente (~400 Tokens), die der RAG-Retrieval trifft')}
                  >
                    {t('{f} Dateien · {c} Chunks', { f: conn.totalFiles, c: conn.totalChunks })}
                  </span>
                )}
                <button
                  className={styles.reindexBtn}
                  onClick={() => _openSettingsForConnection(conn)}
                  title={t('Einstellungen')}
                  style={{ marginLeft: 'auto' }}
                >
                  <FaSlidersH size={14} />
                </button>
                <button
                  className={styles.consentToggle}
                  onClick={() => _handleConsentToggle(conn.id, conn.knowledgeIngestionEnabled)}
                  title={conn.knowledgeIngestionEnabled ? t('Wissensdatenbank deaktivieren') : t('Wissensdatenbank aktivieren')}
                >
                  {conn.knowledgeIngestionEnabled ? <FaToggleOn size={20} /> : <FaToggleOff size={20} />}
                </button>
              </div>

              {!conn.knowledgeIngestionEnabled && conn.dataSources.length > 0 && (
                <div className={styles.consentWarning}>
                  {t('Wissensdatenbank deaktiviert — Indexierung pausiert. Toggle aktivieren um Daten zu indexieren.')}
                </div>
              )}

              {/* Status banner: priority is Running > Error-newer-than-Success > Success > Reindex-Hint.
                  This way a stale error doesn't override a fresh successful resync, and the
                  spinner is never shown without a real job behind it. */}
              {conn.runningJobs.length > 0 ? (
                <div className={styles.jobBanner}>
                  <FaSync className={styles.spinIcon} />
                  <span>{conn.runningJobs[0].progressMessage || t('Synchronisierung läuft...')}</span>
                  <button className={styles.stopBtn} onClick={() => _handleStop(conn.id)} title={t('Indexierung stoppen')}>
                    <FaStop size={12} /> {t('Stop')}
                  </button>
                </div>
              ) : (() => {
                const errAt = conn.lastError?.finishedAt ?? 0;
                const okAt = conn.lastSuccess?.finishedAt ?? 0;
                const errorIsNewer = !!conn.lastError && errAt > okAt;

                if (errorIsNewer) {
                  return (
                    <div className={styles.errorBanner}>
                      <FaExclamationTriangle />
                      <span>
                        {t('Letzter Sync fehlgeschlagen')} ({_formatRelative(errAt)}): {conn.lastError?.errorMessage || t('unbekannter Fehler')}
                      </span>
                      <button className={styles.reindexBtn} onClick={() => _handleReindex(conn.id)} title={t('Neu indexieren')}>
                        <FaRedo size={12} /> {t('Neu indexieren')}
                      </button>
                    </div>
                  );
                }

                if (conn.lastSuccess) {
                  const s = conn.lastSuccess;
                  const stats = [
                    s.indexed > 0 ? t('{n} neu indexiert', { n: s.indexed }) : null,
                    s.skippedDuplicate > 0 ? t('{n} unverändert', { n: s.skippedDuplicate }) : null,
                    s.skippedPolicy > 0 ? t('{n} übersprungen', { n: s.skippedPolicy }) : null,
                    s.failed > 0 ? t('{n} fehler', { n: s.failed }) : null,
                  ].filter(Boolean).join(' · ');

                  const stop = s.stoppedAtLimit;
                  if (stop) {
                    const budget = s.limits?.[stop];
                    const limitText = _formatLimit(stop, budget, s.bytesProcessed);
                    return (
                      <div className={styles.partialBanner}>
                        <FaExclamationTriangle />
                        <span>
                          <strong>{t('Sync abgeschlossen, Korpus aber unvollständig')}</strong> ({_formatRelative(okAt)})
                          {' — '}
                          {t('Limit {l} erreicht', { l: limitText })}.
                          {stats && <> {stats}.</>}{' '}
                          {t('Weitere Dateien wurden NICHT indexiert.')}
                        </span>
                        <button className={styles.reindexBtn} onClick={() => _openSettingsForConnection(conn)} title={t('Limit für diese Datenquelle anpassen')}>
                          <FaSlidersH size={12} /> {t('Limit anpassen')}
                        </button>
                        <button className={styles.reindexBtn} onClick={() => _handleReindex(conn.id)} title={t('Erneut indexieren')}>
                          <FaRedo size={12} /> {t('Erneut indexieren')}
                        </button>
                      </div>
                    );
                  }

                  return (
                    <div className={styles.successBanner}>
                      <FaCheckCircle />
                      <span>
                        {t('Sync erfolgreich')} {_formatRelative(okAt)}
                        {stats && <> — {stats}</>}
                        {s.durationMs > 0 && <span className={styles.duration}> ({_formatDuration(s.durationMs)})</span>}
                      </span>
                      <button className={styles.reindexBtn} onClick={() => _handleReindex(conn.id)} title={t('Erneut indexieren')}>
                        <FaRedo size={12} /> {t('Erneut indexieren')}
                      </button>
                    </div>
                  );
                }

                if (conn.dataSources.some(ds => ds.ragIndexEnabled) && conn.knowledgeIngestionEnabled) {
                  return (
                    <div className={styles.reindexHint}>
                      <button className={styles.reindexBtn} onClick={() => _handleReindex(conn.id)} title={t('Indexierung starten')}>
                        <FaRedo size={12} /> {t('Indexierung starten')}
                      </button>
                    </div>
                  );
                }
                return null;
              })()}

              <div className={styles.dsList}>
                {conn.dataSources.map(ds => (
                  <div key={ds.id} className={`${styles.dsRow} ${ds.ragIndexEnabled ? styles.dsActive : ''}`}>
                    <span className={styles.dsLabel}>{ds.label || ds.path}</span>
                    <span className={styles.dsType}>{ds.sourceType}</span>
                    <span
                      className={styles.dsChunks}
                      title={t('{f} indizierte Dateien · {c} Embedding-Chunks (~400 Tokens)', { f: ds.fileCount, c: ds.chunkCount })}
                    >
                      {ds.fileCount} {t('Dateien')} · {ds.chunkCount} {t('Chunks')}
                    </span>
                    <button
                      className={styles.dsIndex}
                      onClick={() => _handleDsRagToggle(conn.id, ds)}
                      title={ds.ragIndexEnabled ? t('Indexierung deaktivieren') : t('Indexierung aktivieren')}
                      style={{ cursor: 'pointer', background: 'none', border: 'none', padding: '2px 4px', fontSize: 'inherit' }}
                    >
                      {ds.ragIndexEnabled ? '\uD83E\uDDE0' : '\u2014'}
                    </button>
                  </div>
                ))}
                {conn.dataSources.length === 0 && (
                  <div className={styles.dsEmpty}>{t('Keine Datenquellen konfiguriert')}</div>
                )}
              </div>
                </div>
              </Panel>
            ))}

            {(inventory.featureInstances || []).length > 0 && (
              <Panel variant="card" title={(
                <span className={styles.sectionTitle}>
                  <FaCubes style={{ marginRight: 8 }} />
                  {t('Feature-Daten')}
                </span>
              )} id="rag-feature-data">
                {(inventory.featureInstances || []).map((fi: RagFeatureInstanceDto) => {
                const runningJobs = fi.runningJobs || [];
                const lastSuccess = fi.lastSuccess;
                const lastError = fi.lastError;

                return (
                  <div key={fi.featureInstanceId} className={styles.connectionCard} style={{ marginTop: '1rem' }}>
                    <div className={styles.connectionHeader}>
                      <span className={styles.authority}>{fi.featureCode}</span>
                      <span className={styles.email}>{fi.label}</span>
                      {(fi.fileCount > 0 || fi.chunkCount > 0) && (
                        <span
                          className={styles.connChunks}
                          title={t('Embedding-Fragmente (~400 Tokens), die der RAG-Retrieval trifft')}
                        >
                          {t('{f} Dateien · {c} Chunks', { f: fi.fileCount, c: fi.chunkCount })}
                        </span>
                      )}
                      <span className={styles.dsIndex} title={fi.ragEnabled ? t('RAG aktiv') : t('RAG inaktiv')}>
                        {fi.ragEnabled ? '\uD83E\uDDE0' : '\u2014'}
                      </span>
                    </div>

                    {!fi.ragEnabled && (fi.dataSources || []).length > 0 && (
                      <div className={styles.consentWarning}>
                        {t('RAG-Indexierung ist für keine Datenquelle dieser Feature-Instanz aktiviert. Aktivierung erfolgt in der UDB (Unified Data Bar) der jeweiligen Workspace-Sitzung.')}
                      </div>
                    )}

                    {runningJobs.length > 0 ? (
                      <div className={styles.jobBanner}>
                        <FaSync className={styles.spinIcon} />
                        <span>{runningJobs[0].progressMessage || t('Feature-Daten werden synchronisiert...')}</span>
                      </div>
                    ) : (() => {
                      const errAt = lastError?.finishedAt ?? 0;
                      const okAt = lastSuccess?.finishedAt ?? 0;
                      const errorIsNewer = !!lastError && errAt > okAt;

                      if (errorIsNewer) {
                        return (
                          <div className={styles.errorBanner}>
                            <FaExclamationTriangle />
                            <span>
                              {t('Letzter Sync fehlgeschlagen')} ({_formatRelative(errAt)}): {lastError?.errorMessage || t('unbekannter Fehler')}
                            </span>
                            <button className={styles.reindexBtn} onClick={() => _handleReindexFeature(fi.featureInstanceId)} title={t('Neu indexieren')}>
                              <FaRedo size={12} /> {t('Neu indexieren')}
                            </button>
                          </div>
                        );
                      }

                      if (lastSuccess) {
                        const s = lastSuccess;
                        const stats = [
                          s.indexed > 0 ? t('{n} neu indexiert', { n: s.indexed }) : null,
                          s.skippedDuplicate > 0 ? t('{n} unverändert', { n: s.skippedDuplicate }) : null,
                          s.failed > 0 ? t('{n} fehler', { n: s.failed }) : null,
                        ].filter(Boolean).join(' · ');

                        return (
                          <div className={styles.successBanner}>
                            <FaCheckCircle />
                            <span>
                              {t('Sync erfolgreich')} {_formatRelative(okAt)}
                              {stats && <> — {stats}</>}
                            </span>
                            <button className={styles.reindexBtn} onClick={() => _handleReindexFeature(fi.featureInstanceId)} title={t('Erneut indexieren')}>
                              <FaRedo size={12} /> {t('Erneut indexieren')}
                            </button>
                          </div>
                        );
                      }

                      if (fi.ragEnabled) {
                        return (
                          <div className={styles.reindexHint}>
                            <button className={styles.reindexBtn} onClick={() => _handleReindexFeature(fi.featureInstanceId)} title={t('Indexierung starten')}>
                              <FaRedo size={12} /> {t('Indexierung starten')}
                            </button>
                          </div>
                        );
                      }
                      return null;
                    })()}

                    <div className={styles.dsList}>
                      {(fi.dataSources || []).map(ds => (
                        <div key={ds.id} className={`${styles.dsRow} ${ds.ragIndexEnabled ? styles.dsActive : ''}`}>
                          <span className={styles.dsLabel}>{ds.label || ds.tableName}</span>
                          <span className={styles.dsType}>{ds.featureCode}</span>
                          <span className={styles.dsIndex}>{ds.ragIndexEnabled ? '\uD83E\uDDE0' : '\u2014'}</span>
                        </div>
                      ))}
                      {(fi.dataSources || []).length === 0 && fi.fileCount === 0 && (
                        <div className={styles.dsEmpty}>{t('Keine Datenquellen konfiguriert')}</div>
                      )}
                    </div>
                  </div>
                );
              })}
              </Panel>
            )}

            {(inventory.connections || []).length === 0 && (inventory.featureInstances || []).length === 0 && (
              <Panel variant="card" title={t('Keine Daten')} id="rag-inventory-empty">
                <div className={styles.emptyState}>{t('Keine Daten für diese Sicht vorhanden.')}</div>
              </Panel>
            )}
          </>
        )}
      </StackLayout.Body>

      <DataSourceSettingsModal
        open={!!settingsModal}
        title={settingsModal?.title || ''}
        dataSourceId={settingsModal?.dataSourceId}
        connectionId={settingsModal?.connectionId}
        initialKnowledgeIngestionEnabled={settingsModal?.initialKnowledgeIngestionEnabled}
        showRagSection
        onSaved={() => _fetchInventory()}
        onClose={() => setSettingsModal(null)}
      />
    </StackLayout>
  );
};

export default RagInventoryPage;
