/**
 * DuckLake Panel Component
 * Lakehouse with time travel, ACID transactions, and schema evolution
 */

import React, { useState, useRef, useCallback, useEffect } from 'react';
import { useDuckLake } from '@/hooks/useDuckLake';
import type { SnapshotInfo, SchemaChange } from '@/hooks/useDuckLake';
import { useLanguage } from '@/contexts/LanguageContext';

interface DuckLakePanelProps {
  compact?: boolean;
}

// ============================================
// ResizableNestedTable Component
// Self-contained component with its own resize state
// ============================================
interface ResizableNestedTableProps {
  columns: string[];
  rows: Record<string, unknown>[];
  renderCell: (value: unknown, depth: number) => React.ReactNode;
  depth?: number;
  tableType?: 'array' | 'kv'; // Array of objects or key-value pairs
}

// Helper function to estimate the width needed for nested content
function estimateNestedWidth(value: unknown, depth: number = 0): number {
  if (value === null || value === undefined) return 50;
  
  // Limit recursion depth to prevent infinite loops
  if (depth > 3) return 300;
  
  if (typeof value !== 'object') {
    const str = String(value);
    const isUrl = str.startsWith('http');
    const charWidth = isUrl ? 6 : (str.length > 30 ? 6.5 : 7.5);
    return Math.min(str.length, isUrl ? 60 : 50) * charWidth + 20;
  }
  
  if (Array.isArray(value)) {
    if (value.length === 0) return 50;
    
    // Array of objects - calculate table width
    if (typeof value[0] === 'object' && value[0] !== null) {
      const keys = Object.keys(value[0]);
      let totalWidth = 0;
      
      keys.forEach(key => {
        const headerWidth = key.length * 8 + 30;
        let maxColWidth = headerWidth;
        
        // Sample values in this column
        value.forEach((item: Record<string, unknown>) => {
          const cellWidth = estimateNestedWidth(item[key], depth + 1);
          maxColWidth = Math.max(maxColWidth, cellWidth);
        });
        
        totalWidth += Math.min(400, maxColWidth);
      });
      
      return Math.max(200, totalWidth + 20); // Add some padding
    }
    
    // Array of primitives
    let maxWidth = 100;
    value.forEach(item => {
      maxWidth = Math.max(maxWidth, estimateNestedWidth(item, depth + 1));
    });
    return maxWidth;
  }
  
  // Object (key-value table)
  const entries = Object.entries(value as Record<string, unknown>);
  if (entries.length === 0) return 50;
  
  let maxKeyWidth = 100;
  let maxValueWidth = 150;
  
  entries.forEach(([key, val]) => {
    const keyWidth = key.length * 8 + 30;
    maxKeyWidth = Math.max(maxKeyWidth, Math.min(200, keyWidth));
    
    const valueWidth = estimateNestedWidth(val, depth + 1);
    maxValueWidth = Math.max(maxValueWidth, valueWidth);
  });
  
  return Math.min(200, maxKeyWidth) + Math.min(600, maxValueWidth) + 20;
}

function ResizableNestedTable({ columns, rows, renderCell, depth = 0, tableType = 'array' }: ResizableNestedTableProps) {
  const [colWidths, setColWidths] = useState<Record<string, number>>(() => {
    // Initialize with smart defaults based on column names and actual content
    const widths: Record<string, number> = {};
    
    if (tableType === 'kv') {
      // For key-value tables, analyze actual key and value lengths
      let maxKeyLen = 0;
      let maxValueLen = 0;
      
      rows.forEach(row => {
        const key = Object.keys(row)[0];
        const val = row[key];
        
        // Key length (with some padding for the cell)
        const keyLen = key.length * 8 + 24;
        if (keyLen > maxKeyLen) maxKeyLen = keyLen;
        
        // Value length - calculate recursively for nested content
        if (val !== null && val !== undefined) {
          const estimatedWidth = estimateNestedWidth(val, 0);
          maxValueLen = Math.max(maxValueLen, estimatedWidth);
        }
      });
      
      // Set reasonable bounds - allow wider values for nested content
      widths['key'] = Math.max(100, Math.min(220, maxKeyLen));
      widths['value'] = Math.max(150, Math.min(800, maxValueLen));
    } else {
      // For array tables, calculate per-column with recursive estimation
      columns.forEach(col => {
        // Estimate width based on column name length
        const headerLen = col.length * 8 + 30;
        
        // Sample ALL rows for better accuracy
        let maxContentLen = headerLen;
        
        rows.forEach(row => {
          const val = row[col];
          if (val !== null && val !== undefined) {
            const estimatedWidth = estimateNestedWidth(val, 0);
            maxContentLen = Math.max(maxContentLen, estimatedWidth);
          }
        });
        
        widths[col] = Math.max(80, Math.min(500, maxContentLen));
      });
    }
    
    return widths;
  });

  const resizeRef = useRef<{
    column: string;
    startX: number;
    startWidth: number;
  } | null>(null);

  const handleResizeStart = useCallback((e: React.MouseEvent, column: string) => {
    e.preventDefault();
    e.stopPropagation();
    const startWidth = colWidths[column] || 100;
    resizeRef.current = {
      column,
      startX: e.clientX,
      startWidth
    };
    document.body.style.cursor = 'col-resize';
    document.body.style.userSelect = 'none';
  }, [colWidths]);

  useEffect(() => {
    const handleMouseMove = (e: MouseEvent) => {
      if (!resizeRef.current) return;
      const delta = e.clientX - resizeRef.current.startX;
      const newWidth = Math.max(50, resizeRef.current.startWidth + delta);
      setColWidths(prev => ({
        ...prev,
        [resizeRef.current!.column]: newWidth
      }));
    };

    const handleMouseUp = () => {
      if (resizeRef.current) {
        resizeRef.current = null;
        document.body.style.cursor = '';
        document.body.style.userSelect = '';
      }
    };

    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
    return () => {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };
  }, []);

  if (tableType === 'kv') {
    // Key-value table (for objects)
    const keyWidth = colWidths['key'] || 120;
    const valueWidth = colWidths['value'] || 200;
    const totalWidth = keyWidth + valueWidth;
    return (
      <div className="nested-table-wrapper" style={{ marginLeft: depth * 8, overflowX: 'auto' }}>
        <table className="nested-table kv-table resizable-nested" style={{ tableLayout: 'fixed', width: totalWidth }}>
          <colgroup>
            <col style={{ width: keyWidth }} />
            <col style={{ width: valueWidth }} />
          </colgroup>
          <tbody>
            {rows.map((row, idx) => {
              const key = Object.keys(row)[0];
              const val = row[key];
              return (
                <tr key={idx}>
                  <th 
                    className="kv-key" 
                    style={{ width: keyWidth, maxWidth: keyWidth }}
                  >
                    <span className="kv-key-text">{key}</span>
                    <div 
                      className="col-resize-handle nested-resize"
                      onMouseDown={(e) => handleResizeStart(e, 'key')}
                    />
                  </th>
                  <td 
                    className="kv-value" 
                    style={{ width: valueWidth, maxWidth: valueWidth, position: 'relative' }}
                  >
                    <div className="nested-cell-content">{renderCell(val, depth + 1)}</div>
                    <div 
                      className="col-resize-handle nested-resize"
                      onMouseDown={(e) => handleResizeStart(e, 'value')}
                    />
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    );
  }

  // Array of objects table
  // Calculate total width for the table
  const totalWidth = columns.reduce((sum, col) => sum + (colWidths[col] || 100), 0);
  
  return (
    <div className="nested-table-wrapper" style={{ marginLeft: depth * 8, overflowX: 'auto' }}>
      <table className="nested-table resizable-nested" style={{ tableLayout: 'fixed', width: totalWidth }}>
        <thead>
          <tr>
            {columns.map(col => (
              <th 
                key={col} 
                style={{ width: colWidths[col] || 100, minWidth: 40 }}
                className="resizable-nested-header"
              >
                <span className="nested-header-text">{col}</span>
                <div 
                  className="col-resize-handle nested-resize"
                  onMouseDown={(e) => handleResizeStart(e, col)}
                />
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((row, idx) => (
            <tr key={idx}>
              {columns.map(col => (
                <td key={col} style={{ width: colWidths[col] || 100, maxWidth: colWidths[col] || 100 }}>
                  <div className="nested-cell-content">
                    {renderCell(row[col], depth + 1)}
                  </div>
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}
// ============================================

const TEXT = {
  title: { nl: 'DuckLake Lakehouse', en: 'DuckLake Lakehouse' },
  description: {
    nl: 'Lakehouse met tijdreizen, ACID-transacties en schema-evolutie',
    en: 'Lakehouse with time travel, ACID transactions, and schema evolution',
  },
  connected: { nl: 'Verbonden', en: 'Connected' },
  disconnected: { nl: 'Niet verbonden', en: 'Disconnected' },
  loading: { nl: 'Laden...', en: 'Loading...' },
  refresh: { nl: 'Verversen', en: 'Refresh' },
  tables: { nl: 'Tabellen', en: 'Tables' },
  rows: { nl: 'Rijen', en: 'Rows' },
  columns: { nl: 'Kolommen', en: 'Columns' },
  snapshots: { nl: 'Snapshots', en: 'Snapshots' },
  version: { nl: 'DuckDB Versie', en: 'DuckDB Version' },
  responseTime: { nl: 'Responstijd', en: 'Response time' },
  uptime: { nl: 'Uptime', en: 'Uptime' },
  lastChecked: { nl: 'Laatst gecontroleerd', en: 'Last checked' },
  noTables: { nl: 'Geen tabellen. Upload data om te beginnen.', en: 'No tables. Upload data to get started.' },
  noSnapshots: { nl: 'Geen snapshots beschikbaar.', en: 'No snapshots available.' },
  loadData: { nl: 'Data uploaden', en: 'Upload Data' },
  runQuery: { nl: 'Query uitvoeren', en: 'Run Query' },
  enterQuery: { nl: 'Voer SQL-query in...', en: 'Enter SQL query...' },
  running: { nl: 'Uitvoeren...', en: 'Running...' },
  timeTravel: { nl: 'Tijdreizen', en: 'Time Travel' },
  schemaEvolution: { nl: 'Schema Evolutie', en: 'Schema Evolution' },
  uploadFile: { nl: 'Bestand uploaden', en: 'Upload file' },
  tableName: { nl: 'Tabelnaam', en: 'Table name' },
  uploadMode: { nl: 'Upload modus', en: 'Upload mode' },
  modeAppend: { nl: 'Toevoegen', en: 'Append' },
  modeReplace: { nl: 'Vervangen', en: 'Replace' },
  modeCreate: { nl: 'Nieuw', en: 'Create' },
  dropTable: { nl: 'Verwijderen', en: 'Drop' },
  export: { nl: 'Exporteren', en: 'Export' },
  snapshotId: { nl: 'Snapshot ID', en: 'Snapshot ID' },
  createdAt: { nl: 'Aangemaakt op', en: 'Created at' },
  queryAtSnapshot: { nl: 'Query op snapshot', en: 'Query at snapshot' },
  currentData: { nl: 'Huidige data', en: 'Current data' },
  ducklakeAvailable: { nl: 'DuckLake Actief', en: 'DuckLake Active' },
  ducklakeUnavailable: { nl: 'DuckLake Niet Beschikbaar', en: 'DuckLake Unavailable' },
  catalogType: { nl: 'Catalogus', en: 'Catalog' },
  changeType: { nl: 'Type wijziging', en: 'Change type' },
  columnName: { nl: 'Kolom', en: 'Column' },
  oldType: { nl: 'Oud type', en: 'Old type' },
  newType: { nl: 'Nieuw type', en: 'New type' },
  changedAt: { nl: 'Gewijzigd op', en: 'Changed at' },
  // Data Explorer
  explore: { nl: 'Verkennen', en: 'Explore' },
  dataExplorer: { nl: 'Data Verkenner', en: 'Data Explorer' },
  selectTable: { nl: 'Selecteer een tabel om te verkennen', en: 'Select a table to explore' },
  viewData: { nl: 'Bekijk data', en: 'View data' },
  previewRows: { nl: 'Voorbeeld rijen', en: 'Preview rows' },
  showingRows: { nl: 'Toon rijen', en: 'Showing rows' },
  of: { nl: 'van', en: 'of' },
  previous: { nl: 'Vorige', en: 'Previous' },
  next: { nl: 'Volgende', en: 'Next' },
  backToTables: { nl: '← Terug naar tabellen', en: '← Back to tables' },
  schema: { nl: 'Schema', en: 'Schema' },
  data: { nl: 'Data', en: 'Data' },
  // Search
  search: { nl: 'Zoeken', en: 'Search' },
  searchPlaceholder: { nl: 'Zoek in alle kolommen...', en: 'Search across all columns...' },
  resultsFiltered: { nl: 'resultaten gefilterd', en: 'results filtered' },
  clearSearch: { nl: 'Wissen', en: 'Clear' },
  // Disconnected state messages
  backendRequired: { 
    nl: 'Server-backend Vereist', 
    en: 'Server Backend Required' 
  },
  whyBackendTitle: { 
    nl: 'Waarom een backend?', 
    en: 'Why a backend?' 
  },
  whyBackendExplanation: { 
    nl: 'DuckLake vereist server-side DuckDB met bestandssysteemtoegang voor de catalogus (SQLite/PostgreSQL) en Parquet-databestanden. De DuckLake-extensie is niet beschikbaar voor DuckDB-WASM in de browser.',
    en: 'DuckLake requires server-side DuckDB with file system access for the catalog (SQLite/PostgreSQL) and Parquet data files. The DuckLake extension is not available for DuckDB-WASM in the browser.'
  },
  comingSoon: { 
    nl: 'Binnenkort Beschikbaar', 
    en: 'Coming Soon' 
  },
  comingSoonExplanation: { 
    nl: 'De DuckLake backend wordt binnenkort uitgerold. In de tussentijd kunt u DuckDB WASM gebruiken voor in-browser query\'s.',
    en: 'The DuckLake backend is being deployed soon. In the meantime, you can use DuckDB WASM for in-browser queries.'
  },
  featuresTitle: { 
    nl: 'DuckLake Functies', 
    en: 'DuckLake Features' 
  },
  featureTimeTravel: { 
    nl: 'Tijdreizen - Query historische snapshots van uw data', 
    en: 'Time Travel - Query historical snapshots of your data' 
  },
  featureACID: { 
    nl: 'ACID Transacties - Veilige multi-client schrijfoperaties', 
    en: 'ACID Transactions - Safe multi-client write operations' 
  },
  featureSchema: { 
    nl: 'Schema Evolutie - Track alle schemawijzigingen automatisch', 
    en: 'Schema Evolution - Track all schema changes automatically' 
  },
  featureOpen: { 
    nl: 'Open Formaat - Parquet bestanden + SQLite/PostgreSQL catalogus', 
    en: 'Open Format - Parquet files + SQLite/PostgreSQL catalog' 
  },
  useDuckDBWasm: { 
    nl: 'Gebruik DuckDB WASM', 
    en: 'Use DuckDB WASM' 
  },
};

export function DuckLakePanel({ compact = false }: DuckLakePanelProps) {
  const { language } = useLanguage();
  const t = (key: keyof typeof TEXT) => TEXT[key][language];

  const {
    status,
    stats,
    isLoading,
    error,
    refresh,
    executeQuery,
    uploadData,
    // dropTable - will add back when delete UI is implemented
    exportTable,
  } = useDuckLake();

  const [activeTab, setActiveTab] = useState<'explore' | 'query' | 'timetravel' | 'schema' | 'upload'>('explore');
  const [query, setQuery] = useState('SELECT * FROM information_schema.tables LIMIT 100');
  const [queryResult, setQueryResult] = useState<string | null>(null);
  const [isQueryRunning, setIsQueryRunning] = useState(false);
  const [selectedSnapshot, setSelectedSnapshot] = useState<number | undefined>(undefined);
  const [uploadTableName, setUploadTableName] = useState('');
  const [uploadMode, setUploadMode] = useState<'append' | 'replace' | 'create'>('append');
  const fileInputRef = useRef<HTMLInputElement>(null);
  
  // Data Explorer state
  const [selectedTable, setSelectedTable] = useState<string | null>(null);
  const [tableData, setTableData] = useState<{ columns: string[]; rows: unknown[][] } | null>(null);
  const [isLoadingData, setIsLoadingData] = useState(false);
  const [dataPage, setDataPage] = useState(0);
  const [explorerView, setExplorerView] = useState<'schema' | 'data'>('data');
  const [expandedRow, setExpandedRow] = useState<{ rowIndex: number; data: Record<string, unknown> } | null>(null);
  const [columnWidths, setColumnWidths] = useState<Record<string, number>>({});
  const [rowHeights, setRowHeights] = useState<Record<number, number>>({});
  const [isFullWidth, setIsFullWidth] = useState(false); // Full-width mode for row detail view
  const [showWebArchive, setShowWebArchive] = useState(false); // Web archive viewer mode
  const [searchQuery, setSearchQuery] = useState(''); // Search filter for table data
  const [webArchiveData, setWebArchiveData] = useState<{
    ghcid: string;
    url: string;
    pages: { title: string; path: string; archived_file: string }[];
    claims: { claim_id: string; claim_type: string; text_content: string; xpath: string; hypernym: string; source_page: string }[];
  } | null>(null);
  const [selectedWebPage, setSelectedWebPage] = useState<string | null>(null);
  const PAGE_SIZE = 50;
  
  // Refs for resize tracking
  const resizeRef = useRef<{
    type: 'column' | 'row';
    key: string | number;
    startPos: number;
    startSize: number;
  } | null>(null);
  const tableRef = useRef<HTMLTableElement>(null);

  // Calculate optimal column width based on content
  const calculateOptimalWidth = useCallback((columnName: string, values: unknown[]): number => {
    const headerLen = columnName.length * 9; // Approximate char width
    let maxContentLen = 0;
    
    for (const val of values.slice(0, 20)) { // Sample first 20 rows
      if (val === null || val === undefined) continue;
      const str = typeof val === 'object' ? JSON.stringify(val) : String(val);
      const len = Math.min(str.length, 100) * 8; // Cap at 100 chars
      if (len > maxContentLen) maxContentLen = len;
    }
    
    // Return width between 80 and 400px
    return Math.max(80, Math.min(400, Math.max(headerLen, maxContentLen) + 24));
  }, []);

  // Initialize column widths when table data loads
  useEffect(() => {
    if (tableData && tableData.columns.length > 0) {
      const widths: Record<string, number> = {};
      tableData.columns.forEach((col, idx) => {
        const colValues = tableData.rows.map(row => row[idx]);
        widths[col] = calculateOptimalWidth(col, colValues);
      });
      setColumnWidths(widths);
      setRowHeights({}); // Reset row heights
    }
  }, [tableData, calculateOptimalWidth]);

  // Handle mouse down on column resize handle
  const handleColumnResizeStart = useCallback((e: React.MouseEvent, columnName: string) => {
    e.preventDefault();
    e.stopPropagation();
    resizeRef.current = {
      type: 'column',
      key: columnName,
      startPos: e.clientX,
      startSize: columnWidths[columnName] || 150
    };
    document.body.style.cursor = 'col-resize';
    document.body.style.userSelect = 'none';
  }, [columnWidths]);

  // Handle mouse down on row resize handle
  const handleRowResizeStart = useCallback((e: React.MouseEvent, rowIndex: number, currentHeight: number) => {
    e.preventDefault();
    e.stopPropagation();
    resizeRef.current = {
      type: 'row',
      key: rowIndex,
      startPos: e.clientY,
      startSize: currentHeight
    };
    document.body.style.cursor = 'row-resize';
    document.body.style.userSelect = 'none';
  }, []);

  // Handle mouse move during resize
  useEffect(() => {
    const handleMouseMove = (e: MouseEvent) => {
      if (!resizeRef.current) return;
      
      const { type, key, startPos, startSize } = resizeRef.current;
      
      if (type === 'column') {
        const delta = e.clientX - startPos;
        const newWidth = Math.max(60, startSize + delta);
        setColumnWidths(prev => ({ ...prev, [key]: newWidth }));
      } else {
        const delta = e.clientY - startPos;
        const newHeight = Math.max(32, startSize + delta);
        setRowHeights(prev => ({ ...prev, [key as number]: newHeight }));
      }
    };

    const handleMouseUp = () => {
      if (resizeRef.current) {
        resizeRef.current = null;
        document.body.style.cursor = '';
        document.body.style.userSelect = '';
      }
    };

    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
    
    return () => {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };
  }, []);

  const handleRunQuery = async () => {
    setIsQueryRunning(true);
    setQueryResult(null);
    try {
      const result = await executeQuery(query, selectedSnapshot);
      const output = {
        columns: result.columns,
        rowCount: result.rowCount,
        executionTime: `${result.executionTimeMs}ms`,
        snapshotId: result.snapshotId ?? 'current',
        rows: result.rows.slice(0, 100), // Limit display
      };
      setQueryResult(JSON.stringify(output, null, 2));
    } catch (err) {
      setQueryResult(`Error: ${err instanceof Error ? err.message : 'Unknown error'}`);
    } finally {
      setIsQueryRunning(false);
    }
  };

  const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file || !uploadTableName) return;

    try {
      const result = await uploadData(file, uploadTableName, uploadMode);
      alert(`${result.message}\nRows: ${result.rowsInserted}\nSnapshot ID: ${result.snapshotId}`);
      if (fileInputRef.current) {
        fileInputRef.current.value = '';
      }
      setUploadTableName('');
    } catch (err) {
      alert(`Failed to upload: ${err instanceof Error ? err.message : 'Unknown error'}`);
    }
  };

  const handleExport = async (tableName: string, format: 'json' | 'csv' | 'parquet' = 'json') => {
    try {
      const blob = await exportTable(tableName, format, selectedSnapshot);
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `${tableName}${selectedSnapshot ? `_snapshot${selectedSnapshot}` : ''}.${format}`;
      a.click();
      URL.revokeObjectURL(url);
    } catch (err) {
      alert(`Export failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
    }
  };

  // handleDropTable removed - will add back when delete UI is implemented

  const formatUptime = (seconds: number): string => {
    if (seconds < 60) return `${Math.round(seconds)}s`;
    if (seconds < 3600) return `${Math.round(seconds / 60)}m`;
    if (seconds < 86400) return `${Math.round(seconds / 3600)}h`;
    return `${Math.round(seconds / 86400)}d`;
  };

  // Load table data for explorer
  const loadTableData = async (tableName: string) => {
    setIsLoadingData(true);
    setSelectedTable(tableName);
    setDataPage(0);
    setSearchQuery(''); // Reset search when loading new table
    try {
      const offset = 0;
      // Tables are in the 'heritage' schema within DuckLake
      const fullTableName = `heritage.${tableName}`;
      const result = await executeQuery(
        `SELECT * FROM ${fullTableName} LIMIT ${PAGE_SIZE} OFFSET ${offset}`,
        selectedSnapshot
      );
      setTableData({ columns: result.columns, rows: result.rows });
    } catch (err) {
      console.error('Failed to load table data:', err);
      setTableData(null);
    } finally {
      setIsLoadingData(false);
    }
  };

  // Load more data for pagination
  const loadPage = async (page: number) => {
    if (!selectedTable) return;
    setIsLoadingData(true);
    setDataPage(page);
    try {
      const offset = page * PAGE_SIZE;
      // Tables are in the 'heritage' schema within DuckLake
      const fullTableName = `heritage.${selectedTable}`;
      const result = await executeQuery(
        `SELECT * FROM ${fullTableName} LIMIT ${PAGE_SIZE} OFFSET ${offset}`,
        selectedSnapshot
      );
      setTableData({ columns: result.columns, rows: result.rows });
    } catch (err) {
      console.error('Failed to load page:', err);
    } finally {
      setIsLoadingData(false);
    }
  };

  // Get table icon based on name
  const getTableIcon = (tableName: string): string => {
    const name = tableName.toLowerCase();
    if (name.includes('custodian') || name.includes('institution')) return '🏛️';
    if (name.includes('collection')) return '📚';
    if (name.includes('location') || name.includes('geo')) return '📍';
    if (name.includes('person') || name.includes('staff')) return '👤';
    if (name.includes('event')) return '📅';
    if (name.includes('identifier') || name.includes('id')) return '🔖';
    if (name.includes('raw')) return '📦';
    return '📊';
  };

  // Format cell value for display
  const formatCellValue = (value: unknown): string => {
    if (value === null || value === undefined) return '—';
    if (typeof value === 'object') {
      const json = JSON.stringify(value);
      if (json.length > 50) return json.slice(0, 47) + '...';
      return json;
    }
    if (typeof value === 'string') {
      // Check if it's a JSON string
      if ((value.startsWith('{') || value.startsWith('[')) && value.length > 50) {
        return value.slice(0, 47) + '...';
      }
      if (value.length > 80) return value.slice(0, 77) + '...';
    }
    return String(value);
  };

  // Check if a cell value is expandable (JSON object/array or long string)
  const isExpandable = (value: unknown): boolean => {
    if (value === null || value === undefined) return false;
    if (typeof value === 'object') return true;
    if (typeof value === 'string') {
      // JSON strings or long text
      if (value.startsWith('{') || value.startsWith('[')) return true;
      if (value.length > 80) return true;
    }
    return false;
  };

  // Parse a value that might be JSON string into an object
  const parseJsonValue = (value: unknown): unknown => {
    if (value === null || value === undefined) return null;
    if (typeof value === 'object') return value;
    if (typeof value === 'string' && (value.startsWith('{') || value.startsWith('['))) {
      try {
        return JSON.parse(value);
      } catch {
        return value;
      }
    }
    return value;
  };

  // Convert a row array to an object with column names as keys
  const rowToObject = (row: unknown[], columns: string[]): Record<string, unknown> => {
    const obj: Record<string, unknown> = {};
    columns.forEach((col, idx) => {
      obj[col] = row[idx];
    });
    return obj;
  };

  // Get a display name for a row (try common name fields)
  const getRowDisplayName = (rowObj: Record<string, unknown>): string => {
    const nameFields = ['org_name', 'custodian_name', 'name', 'title', 'file_name'];
    for (const field of nameFields) {
      if (rowObj[field] && typeof rowObj[field] === 'string') {
        return rowObj[field] as string;
      }
    }
    return 'Record';
  };

  // Filter rows based on search query (case-insensitive across all columns)
  const filterRowsBySearch = useCallback((rows: unknown[][], _columns: string[], query: string): unknown[][] => {
    if (!query.trim()) return rows;
    const lowerQuery = query.toLowerCase();
    return rows.filter(row => {
      return row.some(cell => {
        if (cell === null || cell === undefined) return false;
        const cellStr = typeof cell === 'object' 
          ? JSON.stringify(cell).toLowerCase() 
          : String(cell).toLowerCase();
        return cellStr.includes(lowerQuery);
      });
    });
  }, []);

  // Get GHCID from row data (try common GHCID fields)
  const getRowGhcid = (rowObj: Record<string, unknown>): string | null => {
    const ghcidFields = ['ghcid', 'ghcid_current', 'file_name'];
    for (const field of ghcidFields) {
      if (rowObj[field] && typeof rowObj[field] === 'string') {
        const val = rowObj[field] as string;
        // GHCID pattern: XX-XX-XXX-X-XXX
        if (val.match(/^[A-Z]{2}-[A-Z0-9]{2,3}-[A-Z]{3}-[A-Z]-/)) {
          return val.replace('.yaml', '');
        }
      }
    }
    return null;
  };

  // Load web archive data for a GHCID
  const loadWebArchive = async (ghcid: string) => {
    if (!ghcid) return;
    try {
      // Query the web_archives table for this GHCID
      const archiveResult = await executeQuery(
        `SELECT ghcid, url, domain, total_pages FROM heritage.web_archives WHERE ghcid = '${ghcid}'`,
        selectedSnapshot
      );
      
      if (archiveResult.rows.length === 0) {
        setWebArchiveData(null);
        return;
      }

      const archive = archiveResult.rows[0];
      const url = archive[1] as string;
      
      // Get pages
      const pagesResult = await executeQuery(
        `SELECT page_title, source_path, archived_file FROM heritage.web_pages WHERE ghcid = '${ghcid}' LIMIT 50`,
        selectedSnapshot
      );
      
      // Get claims (including source_page for filtering)
      const claimsResult = await executeQuery(
        `SELECT claim_id, claim_type, text_content, xpath, hypernym, source_page FROM heritage.web_claims WHERE ghcid = '${ghcid}' LIMIT 200`,
        selectedSnapshot
      );
      
      setWebArchiveData({
        ghcid,
        url,
        pages: pagesResult.rows.map(r => ({
          title: r[0] as string,
          path: r[1] as string,
          archived_file: r[2] as string
        })),
        claims: claimsResult.rows.map(r => ({
          claim_id: r[0] as string,
          claim_type: r[1] as string,
          text_content: r[2] as string,
          xpath: r[3] as string,
          hypernym: r[4] as string,
          source_page: r[5] as string
        }))
      });
      setShowWebArchive(true);
    } catch (err) {
      console.error('Failed to load web archive:', err);
      setWebArchiveData(null);
    }
  };

  // Render a value - either simple or as nested table with resizable columns
  const renderValue = (value: unknown, depth = 0): React.ReactNode => {
    if (value === null || value === undefined) return <span className="null-value">—</span>;
    
    const parsed = parseJsonValue(value);
    
    // Simple values
    if (typeof parsed !== 'object') {
      const strVal = String(parsed);
      if (strVal.startsWith('http://') || strVal.startsWith('https://')) {
        return <a href={strVal} target="_blank" rel="noopener noreferrer" className="link-value">{strVal}</a>;
      }
      return <span className="simple-value">{strVal}</span>;
    }
    
    // Arrays
    if (Array.isArray(parsed)) {
      if (parsed.length === 0) return <span className="empty-value">[ ]</span>;
      
      // Array of objects - render as resizable sub-table
      if (typeof parsed[0] === 'object' && parsed[0] !== null) {
        const keys = Object.keys(parsed[0]);
        return (
          <div className="nested-array">
            <ResizableNestedTable
              columns={keys}
              rows={parsed as Record<string, unknown>[]}
              renderCell={renderValue}
              depth={depth}
              tableType="array"
            />
          </div>
        );
      }
      
      // Array of primitives
      return (
        <ul className="array-list">
          {parsed.map((item, idx) => (
            <li key={idx}>{renderValue(item, depth + 1)}</li>
          ))}
        </ul>
      );
    }
    
    // Objects - render as resizable key-value table
    const entries = Object.entries(parsed as Record<string, unknown>);
    if (entries.length === 0) return <span className="empty-value">{ }</span>;
    
    // Convert entries to rows format for ResizableNestedTable
    const kvRows = entries.map(([key, val]) => ({ [key]: val }));
    
    return (
      <div className="nested-object">
        <ResizableNestedTable
          columns={['key', 'value']}
          rows={kvRows}
          renderCell={renderValue}
          depth={depth}
          tableType="kv"
        />
      </div>
    );
  };

  // Compact view for comparison grid
  if (compact) {
    // Show informative disconnected state
    if (!status.isConnected && !isLoading) {
      return (
        <div className="db-panel compact ducklake-panel disconnected-state">
          <div className="panel-header">
            <span className="panel-icon">🦆</span>
            <h3>DuckLake</h3>
            <span className="status-badge disconnected">
              {t('backendRequired')}
            </span>
          </div>
          <div className="panel-info-compact">
            <p className="info-text">
              {t('comingSoonExplanation')}
            </p>
            <div className="feature-list-compact">
              <span className="feature-chip">⏱️ Time Travel</span>
              <span className="feature-chip">🔒 ACID</span>
              <span className="feature-chip">📊 Schema Evolution</span>
            </div>
          </div>
        </div>
      );
    }

    return (
      <div className="db-panel compact ducklake-panel">
        <div className="panel-header">
          <span className="panel-icon">🦆</span>
          <h3>DuckLake</h3>
          <span className={`status-badge ${status.isConnected ? 'connected' : 'disconnected'}`}>
            {isLoading ? t('loading') : status.isConnected ? t('connected') : t('disconnected')}
          </span>
        </div>
        <div className="panel-stats">
          <div className="stat">
            <span className="stat-value">{stats?.totalTables ?? 0}</span>
            <span className="stat-label">{t('tables')}</span>
          </div>
          <div className="stat">
            <span className="stat-value">{stats?.totalRows?.toLocaleString() ?? 0}</span>
            <span className="stat-label">{t('rows')}</span>
          </div>
          <div className="stat">
            <span className="stat-value">{stats?.totalSnapshots ?? 0}</span>
            <span className="stat-label">{t('snapshots')}</span>
          </div>
          {status.responseTimeMs && (
            <div className="stat">
              <span className="stat-value">{status.responseTimeMs}ms</span>
              <span className="stat-label">{t('responseTime')}</span>
            </div>
          )}
        </div>
        <div className="panel-features">
          <span className={`feature-badge ${status.ducklakeAvailable ? 'active' : 'inactive'}`}>
            {status.ducklakeAvailable ? '⏱️ Time Travel' : '⚠️ Standard Mode'}
          </span>
        </div>
        {error && <div className="panel-error">{error.message}</div>}
      </div>
    );
  }

  // Full view
  // Show informative disconnected state for full view
  if (!status.isConnected && !isLoading) {
    return (
      <div className="db-panel full ducklake-panel disconnected-state">
        {/* Header */}
        <div className="panel-header-full">
          <div className="header-info">
            <span className="panel-icon-large">🦆</span>
            <div>
              <h2>{t('title')}</h2>
              <p>{t('description')}</p>
            </div>
          </div>
          <div className="header-actions">
            <span className="status-badge large disconnected">
              {t('backendRequired')}
            </span>
            <button onClick={refresh} disabled={isLoading} className="refresh-button">
              {t('refresh')}
            </button>
          </div>
        </div>

        {/* Disconnected Content */}
        <div className="disconnected-content">
          {/* Why Backend Section */}
          <div className="info-card">
            <h3>🔧 {t('whyBackendTitle')}</h3>
            <p>{t('whyBackendExplanation')}</p>
          </div>

          {/* Coming Soon Section */}
          <div className="info-card highlight">
            <h3>🚀 {t('comingSoon')}</h3>
            <p>{t('comingSoonExplanation')}</p>
          </div>

          {/* Features Section */}
          <div className="info-card features">
            <h3>✨ {t('featuresTitle')}</h3>
            <ul className="feature-list">
              <li>
                <span className="feature-icon">⏱️</span>
                <span>{t('featureTimeTravel')}</span>
              </li>
              <li>
                <span className="feature-icon">🔒</span>
                <span>{t('featureACID')}</span>
              </li>
              <li>
                <span className="feature-icon">📊</span>
                <span>{t('featureSchema')}</span>
              </li>
              <li>
                <span className="feature-icon">📁</span>
                <span>{t('featureOpen')}</span>
              </li>
            </ul>
          </div>

          {/* Alternative Action */}
          <div className="alternative-action">
            <p>
              <a href="/database" className="action-link">
                🦆 {t('useDuckDBWasm')}
              </a>
              {' '}— {language === 'nl' 
                ? 'In-browser SQL-query\'s op heritage-datasets' 
                : 'In-browser SQL queries on heritage datasets'}
            </p>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="db-panel full ducklake-panel">
      {/* Header */}
      <div className="panel-header-full">
        <div className="header-info">
          <span className="panel-icon-large">🦆</span>
          <div>
            <h2>{t('title')}</h2>
            <p>{t('description')}</p>
          </div>
        </div>
        <div className="header-actions">
          <span className={`status-badge large ${status.isConnected ? 'connected' : 'disconnected'}`}>
            {isLoading ? t('loading') : status.isConnected ? t('connected') : t('disconnected')}
          </span>
          <span className={`feature-badge ${status.ducklakeAvailable ? 'active' : 'inactive'}`}>
            {status.ducklakeAvailable ? t('ducklakeAvailable') : t('ducklakeUnavailable')}
          </span>
          <button onClick={refresh} disabled={isLoading} className="refresh-button">
            {t('refresh')}
          </button>
        </div>
      </div>

      {/* Stats Overview */}
      <div className="stats-row">
        <div className="stat-card">
          <span className="stat-value">{stats?.totalTables ?? 0}</span>
          <span className="stat-label">{t('tables')}</span>
        </div>
        <div className="stat-card">
          <span className="stat-value">{stats?.totalRows?.toLocaleString() ?? 0}</span>
          <span className="stat-label">{t('rows')}</span>
        </div>
        <div className="stat-card">
          <span className="stat-value">{stats?.totalSnapshots ?? 0}</span>
          <span className="stat-label">{t('snapshots')}</span>
        </div>
        <div className="stat-card">
          <span className="stat-value">{status.duckdbVersion || 'N/A'}</span>
          <span className="stat-label">{t('version')}</span>
        </div>
        <div className="stat-card">
          <span className="stat-value">{status.catalogType || 'N/A'}</span>
          <span className="stat-label">{t('catalogType')}</span>
        </div>
        {status.uptimeSeconds && (
          <div className="stat-card">
            <span className="stat-value">{formatUptime(status.uptimeSeconds)}</span>
            <span className="stat-label">{t('uptime')}</span>
          </div>
        )}
        {status.responseTimeMs && (
          <div className="stat-card">
            <span className="stat-value">{status.responseTimeMs}ms</span>
            <span className="stat-label">{t('responseTime')}</span>
          </div>
        )}
      </div>

      {error && (
        <div className="error-banner">
          <strong>Error:</strong> {error.message}
        </div>
      )}

      {/* Tabs */}
      <div className="panel-tabs">
        <button
          className={`tab-btn ${activeTab === 'explore' ? 'active' : ''}`}
          onClick={() => { setActiveTab('explore'); setSelectedTable(null); }}
        >
          🔍 {t('explore')}
        </button>
        <button
          className={`tab-btn ${activeTab === 'query' ? 'active' : ''}`}
          onClick={() => setActiveTab('query')}
        >
          💻 {t('runQuery')}
        </button>
        <button
          className={`tab-btn ${activeTab === 'timetravel' ? 'active' : ''}`}
          onClick={() => setActiveTab('timetravel')}
          disabled={!status.ducklakeAvailable}
        >
          ⏱️ {t('timeTravel')}
        </button>
        <button
          className={`tab-btn ${activeTab === 'schema' ? 'active' : ''}`}
          onClick={() => setActiveTab('schema')}
          disabled={!status.ducklakeAvailable}
        >
          📊 {t('schemaEvolution')}
        </button>
        <button
          className={`tab-btn ${activeTab === 'upload' ? 'active' : ''}`}
          onClick={() => setActiveTab('upload')}
        >
          {t('loadData')}
        </button>
      </div>

      {/* Tab Content */}
      <div className="panel-content">
        {/* Data Explorer Tab */}
        {activeTab === 'explore' && (
          <div className="data-explorer">
            {!selectedTable ? (
              /* Table Selection Grid */
              <div className="table-grid">
                {!stats?.tables.length ? (
                  <p className="empty-message">{t('noTables')}</p>
                ) : (
                  <>
                    <p className="explorer-hint">{t('selectTable')}</p>
                    <div className="table-cards">
                      {stats.tables.map((table) => (
                        <div
                          key={table.name}
                          className="table-card"
                          onClick={() => loadTableData(table.name)}
                          role="button"
                          tabIndex={0}
                          onKeyDown={(e) => e.key === 'Enter' && loadTableData(table.name)}
                        >
                          <div className="table-card-icon">{getTableIcon(table.name)}</div>
                          <div className="table-card-info">
                            <h4>{table.name}</h4>
                            <div className="table-card-stats">
                              <span className="table-stat">
                                <strong>{table.rowCount.toLocaleString()}</strong> {t('rows')}
                              </span>
                              <span className="table-stat">
                                <strong>{table.columnCount}</strong> {t('columns')}
                              </span>
                            </div>
                          </div>
                          <div className="table-card-arrow">→</div>
                        </div>
                      ))}
                    </div>
                  </>
                )}
              </div>
            ) : (
              /* Table Data Viewer */
              <div className="table-viewer">
                <div className="viewer-header">
                  <button
                    className="back-link"
                    onClick={() => { setSelectedTable(null); setTableData(null); }}
                  >
                    {t('backToTables')}
                  </button>
                  <div className="viewer-title">
                    <span className="viewer-icon">{getTableIcon(selectedTable)}</span>
                    <h3>{selectedTable}</h3>
                    {stats?.tables.find(t => t.name === selectedTable) && (
                      <span className="viewer-meta">
                        {stats.tables.find(t => t.name === selectedTable)?.rowCount.toLocaleString()} {t('rows')}
                      </span>
                    )}
                  </div>
                  <div className="viewer-actions">
                    <button
                      className={`view-toggle ${explorerView === 'data' ? 'active' : ''}`}
                      onClick={() => setExplorerView('data')}
                    >
                      📋 {t('data')}
                    </button>
                    <button
                      className={`view-toggle ${explorerView === 'schema' ? 'active' : ''}`}
                      onClick={() => setExplorerView('schema')}
                    >
                      🏗️ {t('schema')}
                    </button>
                    <button
                      className="small-button"
                      onClick={() => handleExport(selectedTable, 'csv')}
                    >
                      📥 CSV
                    </button>
                    <button
                      className="small-button"
                      onClick={() => handleExport(selectedTable, 'json')}
                    >
                      📥 JSON
                    </button>
                  </div>
                </div>

                {/* Search Bar */}
                {explorerView === 'data' && !expandedRow && (
                  <div className="table-search-bar">
                    <div className="search-input-wrapper">
                      <span className="search-icon">🔍</span>
                      <input
                        type="text"
                        value={searchQuery}
                        onChange={(e) => setSearchQuery(e.target.value)}
                        placeholder={t('searchPlaceholder')}
                        className="search-input"
                      />
                      {searchQuery && (
                        <button 
                          className="clear-search-btn"
                          onClick={() => setSearchQuery('')}
                          title={t('clearSearch')}
                        >
                          ✕
                        </button>
                      )}
                    </div>
                    {searchQuery && tableData && (
                      <span className="search-results-count">
                        {filterRowsBySearch(tableData.rows, tableData.columns, searchQuery).length} / {tableData.rows.length} {t('resultsFiltered')}
                      </span>
                    )}
                  </div>
                )}

                {explorerView === 'schema' ? (
                  /* Schema View */
                  <div className="schema-view">
                    <div className="schema-columns">
                      {stats?.tables.find(t => t.name === selectedTable)?.columns.map((col, idx) => (
                        <div key={col.name} className="schema-column">
                          <span className="column-index">{idx + 1}</span>
                          <span className="column-name">{col.name}</span>
                          <span className="column-type">{col.type}</span>
                        </div>
                      ))}
                    </div>
                  </div>
                ) : (
                  /* Data View */
                  <div className="data-view">
                    {isLoadingData ? (
                      <div className="loading-data">
                        <span className="spinner"></span>
                        {t('loading')}
                      </div>
                    ) : expandedRow ? (
                      /* Expanded Row Detail View */
                      <div className={`row-detail-view ${isFullWidth ? 'full-width' : ''}`}>
                        <div className="row-detail-header">
                          <button 
                            className="back-link"
                            onClick={() => setExpandedRow(null)}
                          >
                            ← Back to table
                          </button>
                          <h4 className="row-detail-title">
                            <span className="row-icon">📋</span>
                            {getRowDisplayName(expandedRow.data)}
                          </h4>
                          <span className="row-detail-meta">Row {expandedRow.rowIndex}</span>
                          <button 
                            className={`expand-toggle ${isFullWidth ? 'active' : ''}`}
                            onClick={() => setIsFullWidth(!isFullWidth)}
                            title={isFullWidth ? 'Exit full width' : 'Expand to full width'}
                          >
                            {isFullWidth ? '⊟' : '⊞'}
                          </button>
                          {/* Web Archive Button */}
                          {getRowGhcid(expandedRow.data) && (
                            <button 
                              className={`web-archive-btn ${showWebArchive ? 'active' : ''}`}
                              onClick={() => {
                                if (showWebArchive) {
                                  setShowWebArchive(false);
                                } else {
                                  const ghcid = getRowGhcid(expandedRow.data);
                                  if (ghcid) loadWebArchive(ghcid);
                                }
                              }}
                              title={showWebArchive ? 'Close Web Archive' : 'View Web Archive'}
                            >
                              🌐
                            </button>
                          )}
                        </div>
                        
                        {/* Web Archive Viewer */}
                        {showWebArchive && webArchiveData && (
                          <div className="web-archive-viewer">
                            <div className="web-archive-header">
                              <h5>
                                <span className="archive-icon">🗄️</span>
                                Web Archive: {webArchiveData.ghcid}
                              </h5>
                              <a href={webArchiveData.url} target="_blank" rel="noopener noreferrer" className="original-url">
                                {webArchiveData.url} ↗
                              </a>
                            </div>
                            
                            <div className="web-archive-content">
                              {/* Archived Pages - Wayback style */}
                              <div className="archive-section pages-section">
                                <div className="section-header-row">
                                  <h6>📄 Archived Pages ({webArchiveData.pages.length})</h6>
                                  {selectedWebPage && (
                                    <button 
                                      className="clear-filter-btn"
                                      onClick={() => setSelectedWebPage(null)}
                                      title="Show all pages"
                                    >
                                      ✕ Clear
                                    </button>
                                  )}
                                </div>
                                <div className="pages-list">
                                  {webArchiveData.pages.map((page, idx) => {
                                    // Extract filename from archived_file (e.g., "pages/index.html" -> "index.html")
                                    const pageFile = page.archived_file?.split('/').pop() || '';
                                    return (
                                      <div 
                                        key={idx} 
                                        className={`page-item ${selectedWebPage === pageFile ? 'selected' : ''}`}
                                        onClick={() => setSelectedWebPage(
                                          selectedWebPage === pageFile ? null : pageFile
                                        )}
                                      >
                                        <span className="page-title">{page.title || 'Untitled'}</span>
                                        <span className="page-path">{page.path}</span>
                                      </div>
                                    );
                                  })}
                                  {webArchiveData.pages.length === 0 && (
                                    <div className="no-data">No archived pages found</div>
                                  )}
                                </div>
                              </div>
                              
                              {/* Extracted Claims */}
                              <div className="archive-section claims-section">
                                {(() => {
                                  // Filter claims by selected page
                                  const filteredClaims = selectedWebPage 
                                    ? webArchiveData.claims.filter(c => c.source_page === selectedWebPage)
                                    : webArchiveData.claims;
                                  
                                  return (
                                    <>
                                      <div className="section-header-row">
                                        <h6>
                                          🏷️ Extracted Claims ({filteredClaims.length}
                                          {selectedWebPage && ` / ${webArchiveData.claims.length} total`})
                                          {selectedWebPage && (
                                            <span className="filter-indicator"> — filtered by page</span>
                                          )}
                                        </h6>
                                      </div>
                                      <div className="claims-note">
                                        {selectedWebPage 
                                          ? `Showing claims from: ${selectedWebPage}. Click "Clear" above to see all.`
                                          : 'Click a page to filter claims from that page only.'
                                        }
                                      </div>
                                      <div className="claims-list">
                                        {filteredClaims.map((claim, idx) => (
                                          <div key={idx} className="claim-item">
                                            <div className="claim-header">
                                              <span className={`claim-type ${claim.claim_type.toLowerCase()}`}>
                                                {claim.claim_type}
                                              </span>
                                              {claim.hypernym && (
                                                <span className="claim-hypernym">{claim.hypernym}</span>
                                              )}
                                            </div>
                                            <div className="claim-content">{claim.text_content}</div>
                                            {claim.xpath && (
                                              <div className="claim-xpath" title={claim.xpath}>
                                                📍 {claim.xpath.substring(0, 60)}...
                                              </div>
                                            )}
                                          </div>
                                        ))}
                                        {filteredClaims.length === 0 && (
                                          <div className="no-data">
                                            {selectedWebPage 
                                              ? 'No claims extracted from this page'
                                              : 'No claims extracted'
                                            }
                                          </div>
                                        )}
                                      </div>
                                    </>
                                  );
                                })()}
                              </div>
                            </div>
                          </div>
                        )}
                        
                        <div className="row-detail-content">
                          {Object.entries(expandedRow.data).map(([key, value]) => {
                            const hasNestedData = isExpandable(value);
                            return (
                              <div key={key} className={`field-section ${hasNestedData ? 'has-nested' : ''}`}>
                                <div className="field-header">
                                  <span className="field-name">{key}</span>
                                  {hasNestedData && <span className="field-type-badge">JSON</span>}
                                </div>
                                <div className="field-value">
                                  {renderValue(value)}
                                </div>
                              </div>
                            );
                          })}
                        </div>
                      </div>
                    ) : tableData ? (
                      <>
                        <div className="data-table-wrapper">
                          <table className="data-table explorer-table resizable-table" ref={tableRef}>
                            <thead>
                              <tr>
                                <th className="row-expand-col" style={{ width: 40 }}></th>
                                {tableData.columns.map((col) => (
                                  <th 
                                    key={col} 
                                    style={{ width: columnWidths[col] || 150, minWidth: 60 }}
                                    className="resizable-header"
                                  >
                                    <span className="header-text">{col}</span>
                                    <div 
                                      className="col-resize-handle"
                                      onMouseDown={(e) => handleColumnResizeStart(e, col)}
                                    />
                                  </th>
                                ))}
                              </tr>
                            </thead>
                            <tbody>
                              {(() => {
                                const filteredRows = filterRowsBySearch(tableData.rows, tableData.columns, searchQuery);
                                return filteredRows.map((row, rowIdx) => {
                                  const rowObj = rowToObject(row, tableData.columns);
                                  const rowHeight = rowHeights[rowIdx];
                                  // Find original index for accurate row numbering
                                  const originalIdx = tableData.rows.indexOf(row);
                                  return (
                                    <tr 
                                      key={rowIdx} 
                                      className="clickable-row"
                                      style={rowHeight ? { height: rowHeight } : undefined}
                                      onClick={() => setExpandedRow({
                                        rowIndex: dataPage * PAGE_SIZE + originalIdx + 1,
                                        data: rowObj
                                      })}
                                    >
                                      <td className="row-expand-cell">
                                        <span className="expand-arrow">▶</span>
                                        <div 
                                          className="row-resize-handle"
                                          onMouseDown={(e) => handleRowResizeStart(e, rowIdx, rowHeight || 40)}
                                          onClick={(e) => e.stopPropagation()}
                                        />
                                      </td>
                                      {row.map((cell, cellIdx) => (
                                        <td 
                                          key={cellIdx} 
                                          title={String(cell)}
                                          style={{ maxWidth: columnWidths[tableData.columns[cellIdx]] || 150 }}
                                        >
                                          <div className="cell-content">
                                            {formatCellValue(cell)}
                                          </div>
                                        </td>
                                      ))}
                                    </tr>
                                  );
                                });
                              })()}
                            </tbody>
                          </table>
                        </div>
                        <div className="pagination">
                          <button
                            className="page-btn"
                            disabled={dataPage === 0}
                            onClick={() => loadPage(dataPage - 1)}
                          >
                            ← {t('previous')}
                          </button>
                          <span className="page-info">
                            {searchQuery 
                              ? `${filterRowsBySearch(tableData.rows, tableData.columns, searchQuery).length} ${t('resultsFiltered')}`
                              : `${t('showingRows')} ${dataPage * PAGE_SIZE + 1} - ${dataPage * PAGE_SIZE + tableData.rows.length}`
                            }
                          </span>
                          <button
                            className="page-btn"
                            disabled={tableData.rows.length < PAGE_SIZE}
                            onClick={() => loadPage(dataPage + 1)}
                          >
                            {t('next')} →
                          </button>
                        </div>
                      </>
                    ) : (
                      <p className="empty-message">No data available</p>
                    )}
                  </div>
                )}
              </div>
            )}
          </div>
        )}

        {/* Query Tab */}
        {activeTab === 'query' && (
          <div className="query-section">
            {status.ducklakeAvailable && stats?.snapshots && stats.snapshots.length > 0 && (
              <div className="snapshot-selector">
                <label>{t('queryAtSnapshot')}:</label>
                <select
                  value={selectedSnapshot ?? ''}
                  onChange={(e) => setSelectedSnapshot(e.target.value ? parseInt(e.target.value) : undefined)}
                  className="snapshot-select"
                >
                  <option value="">{t('currentData')}</option>
                  {stats.snapshots.map((snap: SnapshotInfo) => (
                    <option key={snap.snapshotId} value={snap.snapshotId}>
                      Snapshot #{snap.snapshotId} - {new Date(snap.createdAt).toLocaleString()}
                    </option>
                  ))}
                </select>
              </div>
            )}
            <textarea
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              className="query-input"
              rows={8}
              placeholder={t('enterQuery')}
            />
            <div className="query-actions">
              <button
                onClick={handleRunQuery}
                disabled={isQueryRunning}
                className="primary-button"
              >
                {isQueryRunning ? t('running') : t('runQuery')}
              </button>
              {selectedSnapshot && (
                <span className="snapshot-indicator">
                  ⏱️ Querying at Snapshot #{selectedSnapshot}
                </span>
              )}
            </div>
            {queryResult && <pre className="query-result">{queryResult}</pre>}
          </div>
        )}

        {/* Time Travel Tab */}
        {activeTab === 'timetravel' && (
          <div className="timetravel-section">
            <h3>⏱️ {t('timeTravel')}</h3>
            <p className="section-description">
              Query historical versions of your data using snapshots. Each write operation creates a new snapshot.
            </p>
            {!stats?.snapshots?.length ? (
              <p className="empty-message">{t('noSnapshots')}</p>
            ) : (
              <table className="data-table">
                <thead>
                  <tr>
                    <th>{t('snapshotId')}</th>
                    <th>{t('createdAt')}</th>
                    <th>Actions</th>
                  </tr>
                </thead>
                <tbody>
                  {stats.snapshots.map((snap: SnapshotInfo) => (
                    <tr key={snap.snapshotId}>
                      <td><code>#{snap.snapshotId}</code></td>
                      <td>{new Date(snap.createdAt).toLocaleString()}</td>
                      <td>
                        <button
                          className="small-button"
                          onClick={() => {
                            setSelectedSnapshot(snap.snapshotId);
                            setActiveTab('query');
                          }}
                        >
                          Query this snapshot
                        </button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </div>
        )}

        {/* Schema Evolution Tab */}
        {activeTab === 'schema' && (
          <div className="schema-section">
            <h3>📊 {t('schemaEvolution')}</h3>
            <p className="section-description">
              Track all schema changes over time. DuckLake automatically records column additions, type changes, and more.
            </p>
            {!stats?.schemaChanges?.length ? (
              <p className="empty-message">No schema changes recorded yet.</p>
            ) : (
              <table className="data-table">
                <thead>
                  <tr>
                    <th>{t('tableName')}</th>
                    <th>{t('changeType')}</th>
                    <th>{t('columnName')}</th>
                    <th>{t('oldType')}</th>
                    <th>{t('newType')}</th>
                    <th>{t('changedAt')}</th>
                  </tr>
                </thead>
                <tbody>
                  {stats.schemaChanges.map((change: SchemaChange) => (
                    <tr key={change.changeId}>
                      <td><code>{change.tableName}</code></td>
                      <td>
                        <span className={`change-badge ${change.changeType.toLowerCase()}`}>
                          {change.changeType}
                        </span>
                      </td>
                      <td><code>{change.columnName || '-'}</code></td>
                      <td><code>{change.oldType || '-'}</code></td>
                      <td><code>{change.newType || '-'}</code></td>
                      <td>{new Date(change.changedAt).toLocaleString()}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </div>
        )}

        {/* Upload Tab */}
        {activeTab === 'upload' && (
          <div className="upload-section">
            <h3>{t('loadData')}</h3>
            <p className="section-description">
              Upload JSON, CSV, or Parquet files. Each upload creates a new snapshot for time travel.
            </p>
            <div className="form-group">
              <label>{t('tableName')}:</label>
              <input
                type="text"
                value={uploadTableName}
                onChange={(e) => setUploadTableName(e.target.value)}
                placeholder="my_table"
                className="text-input"
              />
            </div>
            <div className="form-group">
              <label>{t('uploadMode')}:</label>
              <select
                value={uploadMode}
                onChange={(e) => setUploadMode(e.target.value as 'append' | 'replace' | 'create')}
                className="mode-select"
              >
                <option value="append">{t('modeAppend')} - Add rows to existing table</option>
                <option value="replace">{t('modeReplace')} - Drop and recreate table</option>
                <option value="create">{t('modeCreate')} - Create new table (error if exists)</option>
              </select>
            </div>
            <div className="form-group">
              <label>{t('uploadFile')}:</label>
              <input
                type="file"
                ref={fileInputRef}
                onChange={handleFileUpload}
                accept=".json,.csv,.parquet"
                disabled={!uploadTableName}
                className="file-input"
              />
              <small>Supported formats: JSON, CSV, Parquet</small>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
