/**
 * Oxigraph Panel Component
 * SPARQL triplestore for Linked Data
 */

import { useState, useRef, useEffect, useCallback } from 'react';
import * as d3 from 'd3';
import { useOxigraph } from '@/hooks/useOxigraph';
import type { OxigraphGraphNode, OxigraphGraphData } from '@/hooks/useOxigraph';
import { useLanguage } from '@/contexts/LanguageContext';

interface OxigraphPanelProps {
  compact?: boolean;
}

const TEXT = {
  title: { nl: 'Oxigraph Triplestore', en: 'Oxigraph Triplestore' },
  description: {
    nl: 'SPARQL-endpoint voor Linked Data en RDF-queries',
    en: 'SPARQL endpoint for Linked Data and RDF queries',
  },
  connected: { nl: 'Verbonden', en: 'Connected' },
  disconnected: { nl: 'Niet verbonden', en: 'Disconnected' },
  loading: { nl: 'Laden...', en: 'Loading...' },
  refresh: { nl: 'Verversen', en: 'Refresh' },
  triples: { nl: 'Triples', en: 'Triples' },
  graphs: { nl: 'Graphs', en: 'Graphs' },
  classes: { nl: 'Klassen', en: 'Classes' },
  predicates: { nl: 'Predicaten', en: 'Predicates' },
  namespaces: { nl: 'Namespaces', en: 'Namespaces' },
  responseTime: { nl: 'Responstijd', en: 'Response time' },
  noData: { nl: 'Geen data gevonden.', en: 'No data found.' },
  runQuery: { nl: 'Query uitvoeren', en: 'Run Query' },
  enterQuery: { nl: 'Voer SPARQL-query in...', en: 'Enter SPARQL query...' },
  running: { nl: 'Uitvoeren...', en: 'Running...' },
  uploadData: { nl: 'Data uploaden', en: 'Upload Data' },
  uploadDescription: {
    nl: 'Laad RDF-data in de triplestore',
    en: 'Load RDF data into the triplestore',
  },
  rdfFormat: { nl: 'Formaat', en: 'Format' },
  targetGraph: { nl: 'Doelgraph', en: 'Target Graph' },
  graphName: { nl: 'Graph', en: 'Graph' },
  tripleCount: { nl: 'Triples', en: 'Triples' },
  export: { nl: 'Exporteren', en: 'Export' },
  clearAll: { nl: 'Alles wissen', en: 'Clear All' },
  confirmClear: {
    nl: 'Weet u zeker dat u alle data wilt wissen?',
    en: 'Are you sure you want to clear all data?',
  },
  prefix: { nl: 'Prefix', en: 'Prefix' },
  namespace: { nl: 'Namespace', en: 'Namespace' },
  class: { nl: 'Klasse', en: 'Class' },
  predicate: { nl: 'Predicaat', en: 'Predicate' },
  count: { nl: 'Aantal', en: 'Count' },
  explore: { nl: 'Verkennen', en: 'Explore' },
  graphView: { nl: 'Graaf', en: 'Graph' },
  tableView: { nl: 'Tabel', en: 'Table' },
  loadGraph: { nl: 'Graaf laden', en: 'Load Graph' },
  allClasses: { nl: 'Alle klassen', en: 'All Classes' },
  selectClass: { nl: 'Selecteer klasse...', en: 'Select class...' },
  nodes: { nl: 'Knooppunten', en: 'Nodes' },
  edges: { nl: 'Verbindingen', en: 'Edges' },
  search: { nl: 'Zoeken...', en: 'Search...' },
  attributes: { nl: 'Attributen', en: 'Attributes' },
};

/**
 * Shorten a URI for display by replacing common prefixes
 */
function shortenUri(uri: string): string {
  const prefixes: Record<string, string> = {
    'http://www.w3.org/1999/02/22-rdf-syntax-ns#': 'rdf:',
    'http://www.w3.org/2000/01/rdf-schema#': 'rdfs:',
    'http://www.w3.org/2002/07/owl#': 'owl:',
    'http://www.w3.org/2001/XMLSchema#': 'xsd:',
    'http://www.w3.org/2004/02/skos/core#': 'skos:',
    'http://purl.org/dc/terms/': 'dct:',
    'http://purl.org/dc/elements/1.1/': 'dc:',
    'http://xmlns.com/foaf/0.1/': 'foaf:',
    'http://schema.org/': 'schema:',
    'http://www.w3.org/ns/prov#': 'prov:',
    'http://www.cidoc-crm.org/cidoc-crm/': 'crm:',
    'https://www.ica.org/standards/RiC/ontology#': 'rico:',
    'http://data.europa.eu/m8g/': 'cpov:',
    'https://identifier.overheid.nl/tooi/def/ont/': 'tooi:',
    'http://www.w3.org/ns/org#': 'org:',
    'https://w3id.org/heritage/custodian/': 'hc:',
  };

  for (const [namespace, prefix] of Object.entries(prefixes)) {
    if (uri.startsWith(namespace)) {
      return prefix + uri.slice(namespace.length);
    }
  }

  const lastPart = uri.split(/[#/]/).pop();
  if (lastPart && lastPart.length < uri.length - 10) {
    return '...' + lastPart;
  }
  return uri;
}

// D3 node interface extending simulation datum
interface D3Node extends d3.SimulationNodeDatum {
  id: string;
  label: string;
  type: string;
  entityType: string;
  attributes: Record<string, unknown>;
}

// D3 link interface
interface D3Link extends d3.SimulationLinkDatum<D3Node> {
  id: string;
  predicate: string;
  predicateLabel: string;
}

// ============================================================================
// Graph Visualization Component for Oxigraph
// ============================================================================

interface OxigraphGraphVisualizationProps {
  data: OxigraphGraphData;
  width?: number;
  height?: number;
  onNodeClick?: (node: OxigraphGraphNode) => void;
}

function OxigraphGraphVisualization({ data, width = 800, height = 500, onNodeClick }: OxigraphGraphVisualizationProps) {
  const svgRef = useRef<SVGSVGElement>(null);

  const getNodeColor = useCallback((entityType: string): string => {
    const colors: Record<string, string> = {
      'schema:Museum': '#e74c3c',
      'schema:Library': '#3498db',
      'schema:ArchiveOrganization': '#2ecc71',
      'hc:HeritageCustodian': '#9b59b6',
      'cpov:PublicOrganisation': '#1abc9c',
      'schema:Place': '#16a085',
      'schema:Organization': '#f39c12',
      'crm:E74_Group': '#e67e22',
      'rico:CorporateBody': '#d35400',
    };
    return colors[entityType] || '#95a5a6';
  }, []);

  useEffect(() => {
    if (!svgRef.current || data.nodes.length === 0) return;

    const svg = d3.select(svgRef.current);
    svg.selectAll('*').remove();

    // Create container with zoom
    const container = svg.append('g').attr('class', 'graph-container');

    // Arrow marker
    const defs = svg.append('defs');
    defs.append('marker')
      .attr('id', 'oxigraph-arrow')
      .attr('viewBox', '0 -5 10 10')
      .attr('refX', 25)
      .attr('refY', 0)
      .attr('markerWidth', 6)
      .attr('markerHeight', 6)
      .attr('orient', 'auto')
      .append('path')
      .attr('d', 'M0,-5L10,0L0,5')
      .attr('fill', '#999');

    // Create D3 nodes and links
    const d3Nodes: D3Node[] = data.nodes.map(n => ({
      ...n,
      x: width / 2 + (Math.random() - 0.5) * 200,
      y: height / 2 + (Math.random() - 0.5) * 200,
    }));

    const nodeMap = new Map(d3Nodes.map(n => [n.id, n]));
    
    const d3Links: D3Link[] = data.edges
      .filter(e => nodeMap.has(e.source) && nodeMap.has(e.target))
      .map(e => ({
        id: e.id,
        source: nodeMap.get(e.source)!,
        target: nodeMap.get(e.target)!,
        predicate: e.predicate,
        predicateLabel: e.predicateLabel,
      }));

    // Force simulation
    const simulation = d3.forceSimulation<D3Node>(d3Nodes)
      .force('link', d3.forceLink<D3Node, D3Link>(d3Links).id(d => d.id).distance(120))
      .force('charge', d3.forceManyBody().strength(-400))
      .force('center', d3.forceCenter(width / 2, height / 2))
      .force('collision', d3.forceCollide().radius(40));

    // Links
    const link = container.append('g')
      .attr('class', 'links')
      .selectAll('line')
      .data(d3Links)
      .join('line')
      .attr('stroke', '#999')
      .attr('stroke-width', 2)
      .attr('stroke-opacity', 0.6)
      .attr('marker-end', 'url(#oxigraph-arrow)');

    // Link labels
    const linkLabel = container.append('g')
      .attr('class', 'link-labels')
      .selectAll('text')
      .data(d3Links)
      .join('text')
      .attr('font-size', 9)
      .attr('fill', '#666')
      .attr('text-anchor', 'middle')
      .text(d => d.predicateLabel);

    // Nodes
    const node = container.append('g')
      .attr('class', 'nodes')
      .selectAll('circle')
      .data(d3Nodes)
      .join('circle')
      .attr('r', 15)
      .attr('fill', d => getNodeColor(d.entityType))
      .attr('stroke', '#fff')
      .attr('stroke-width', 2)
      .style('cursor', 'pointer')
      .on('click', (_event, d) => {
        onNodeClick?.({
          id: d.id,
          label: d.label,
          type: d.type,
          entityType: d.entityType,
          attributes: d.attributes,
        });
      })
      .call(d3.drag<SVGCircleElement, D3Node>()
        .on('start', (event, d) => {
          if (!event.active) simulation.alphaTarget(0.3).restart();
          d.fx = d.x;
          d.fy = d.y;
        })
        .on('drag', (event, d) => {
          d.fx = event.x;
          d.fy = event.y;
        })
        .on('end', (event, d) => {
          if (!event.active) simulation.alphaTarget(0);
          d.fx = null;
          d.fy = null;
        }) as any);

    // Node labels
    const nodeLabel = container.append('g')
      .attr('class', 'node-labels')
      .selectAll('text')
      .data(d3Nodes)
      .join('text')
      .attr('font-size', 11)
      .attr('dx', 18)
      .attr('dy', 4)
      .attr('fill', '#333')
      .text(d => d.label.length > 20 ? d.label.substring(0, 17) + '...' : d.label);

    // Simulation tick
    simulation.on('tick', () => {
      link
        .attr('x1', d => (d.source as D3Node).x!)
        .attr('y1', d => (d.source as D3Node).y!)
        .attr('x2', d => (d.target as D3Node).x!)
        .attr('y2', d => (d.target as D3Node).y!);

      linkLabel
        .attr('x', d => ((d.source as D3Node).x! + (d.target as D3Node).x!) / 2)
        .attr('y', d => ((d.source as D3Node).y! + (d.target as D3Node).y!) / 2 - 5);

      node
        .attr('cx', d => d.x!)
        .attr('cy', d => d.y!);

      nodeLabel
        .attr('x', d => d.x!)
        .attr('y', d => d.y!);
    });

    // Zoom behavior
    const zoom = d3.zoom<SVGSVGElement, unknown>()
      .scaleExtent([0.1, 4])
      .on('zoom', (event) => {
        container.attr('transform', event.transform);
      });

    svg.call(zoom as any);

  }, [data, width, height, getNodeColor, onNodeClick]);

  return (
    <svg
      ref={svgRef}
      width={width}
      height={height}
      style={{ background: '#fafafa', borderRadius: '8px', border: '1px solid #e0e0e0' }}
    />
  );
}

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

  const {
    status,
    stats,
    isLoading,
    error,
    refresh,
    executeSparql,
    loadRdfData,
    clearGraph,
    exportGraph,
    getGraphData,
  } = useOxigraph();

  const [activeTab, setActiveTab] = useState<'explore' | 'graphs' | 'classes' | 'predicates' | 'namespaces' | 'query' | 'upload'>('explore');
  const [query, setQuery] = useState('SELECT * WHERE { ?s ?p ?o } LIMIT 10');
  const [queryResult, setQueryResult] = useState<string | null>(null);
  const [isQueryRunning, setIsQueryRunning] = useState(false);
  const [uploadFormat, setUploadFormat] = useState('ttl');
  const [uploadGraph, setUploadGraph] = useState('');
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Explore tab state
  const [selectedClass, setSelectedClass] = useState<string | null>(null);
  const [exploreViewMode, setExploreViewMode] = useState<'graph' | 'table'>('graph');
  const [graphData, setGraphData] = useState<OxigraphGraphData | null>(null);
  const [isLoadingData, setIsLoadingData] = useState(false);
  const [searchTerm, setSearchTerm] = useState('');
  const [selectedNode, setSelectedNode] = useState<OxigraphGraphNode | null>(null);

  const handleRunQuery = async () => {
    setIsQueryRunning(true);
    setQueryResult(null);
    try {
      const result = await executeSparql(query);
      setQueryResult(JSON.stringify(result, 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) return;

    try {
      const content = await file.text();
      await loadRdfData(content, uploadFormat, uploadGraph || undefined);
      alert(`Successfully loaded ${file.name}`);
      if (fileInputRef.current) {
        fileInputRef.current.value = '';
      }
    } catch (err) {
      alert(`Failed to load file: ${err instanceof Error ? err.message : 'Unknown error'}`);
    }
  };

  const handleExport = async (graphName?: string) => {
    try {
      const data = await exportGraph(graphName, 'ttl');
      const blob = new Blob([data], { type: 'text/turtle' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = graphName ? `${graphName.split('/').pop()}.ttl` : 'export.ttl';
      a.click();
      URL.revokeObjectURL(url);
    } catch (err) {
      alert(`Export failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
    }
  };

  const handleClearAll = async () => {
    if (window.confirm(t('confirmClear'))) {
      try {
        await clearGraph();
        alert('All data cleared');
      } catch (err) {
        alert(`Clear failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
      }
    }
  };

  // Handler for loading graph visualization data
  const handleLoadGraphData = async (rdfClass?: string) => {
    setSelectedClass(rdfClass || null);
    setIsLoadingData(true);
    setGraphData(null);
    setSelectedNode(null);
    try {
      const data = await getGraphData(rdfClass, 100);
      setGraphData(data);
    } catch (err) {
      console.error('Failed to load graph data:', err);
    } finally {
      setIsLoadingData(false);
    }
  };

  // Filter nodes by search term
  const filteredNodes = graphData?.nodes.filter(n => {
    if (!searchTerm) return true;
    const term = searchTerm.toLowerCase();
    return (
      n.label.toLowerCase().includes(term) ||
      n.id.toLowerCase().includes(term) ||
      n.entityType.toLowerCase().includes(term)
    );
  }) ?? [];

  // Compact view for comparison grid
  if (compact) {
    return (
      <div className="db-panel compact oxigraph-panel">
        <div className="panel-header">
          <span className="panel-icon">🔗</span>
          <h3>Oxigraph</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?.totalTriples?.toLocaleString() ?? 0}</span>
            <span className="stat-label">{t('triples')}</span>
          </div>
          <div className="stat">
            <span className="stat-value">{stats?.totalGraphs ?? 0}</span>
            <span className="stat-label">{t('graphs')}</span>
          </div>
          <div className="stat">
            <span className="stat-value">{stats?.classes.length ?? 0}</span>
            <span className="stat-label">{t('classes')}</span>
          </div>
        </div>
        {error && <div className="panel-error">{error.message}</div>}
      </div>
    );
  }

  // Full view
  return (
    <div className="db-panel full oxigraph-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>
          <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?.totalTriples?.toLocaleString() ?? 0}</span>
          <span className="stat-label">{t('triples')}</span>
        </div>
        <div className="stat-card">
          <span className="stat-value">{stats?.totalGraphs ?? 0}</span>
          <span className="stat-label">{t('graphs')}</span>
        </div>
        <div className="stat-card">
          <span className="stat-value">{stats?.classes.length ?? 0}</span>
          <span className="stat-label">{t('classes')}</span>
        </div>
        <div className="stat-card">
          <span className="stat-value">{stats?.predicates.length ?? 0}</span>
          <span className="stat-label">{t('predicates')}</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')}
        >
          {t('explore')}
        </button>
        <button
          className={`tab-btn ${activeTab === 'graphs' ? 'active' : ''}`}
          onClick={() => setActiveTab('graphs')}
        >
          {t('graphs')} ({stats?.graphs.length ?? 0})
        </button>
        <button
          className={`tab-btn ${activeTab === 'classes' ? 'active' : ''}`}
          onClick={() => setActiveTab('classes')}
        >
          {t('classes')} ({stats?.classes.length ?? 0})
        </button>
        <button
          className={`tab-btn ${activeTab === 'predicates' ? 'active' : ''}`}
          onClick={() => setActiveTab('predicates')}
        >
          {t('predicates')} ({stats?.predicates.length ?? 0})
        </button>
        <button
          className={`tab-btn ${activeTab === 'namespaces' ? 'active' : ''}`}
          onClick={() => setActiveTab('namespaces')}
        >
          {t('namespaces')}
        </button>
        <button
          className={`tab-btn ${activeTab === 'query' ? 'active' : ''}`}
          onClick={() => setActiveTab('query')}
        >
          {t('runQuery')}
        </button>
        <button
          className={`tab-btn ${activeTab === 'upload' ? 'active' : ''}`}
          onClick={() => setActiveTab('upload')}
        >
          {t('uploadData')}
        </button>
      </div>

      {/* Tab Content */}
      <div className="panel-content">
        {/* EXPLORE TAB - Graph Visualization */}
        {activeTab === 'explore' && (
          <div className="explore-section">
            {/* Class Selector and Controls */}
            <div className="explore-header">
              <div className="explore-controls">
                <select
                  className="class-select"
                  value={selectedClass || ''}
                  onChange={(e) => handleLoadGraphData(e.target.value || undefined)}
                >
                  <option value="">{t('allClasses')}</option>
                  {stats?.classes.map((cls, index) => (
                    <option key={index} value={cls.class}>
                      {shortenUri(cls.class)} ({cls.count})
                    </option>
                  ))}
                </select>
                <button
                  className="primary-button"
                  onClick={() => handleLoadGraphData(selectedClass || undefined)}
                  disabled={isLoadingData}
                >
                  {isLoadingData ? t('loading') : t('loadGraph')}
                </button>
              </div>
              {graphData && (
                <div className="graph-stats">
                  <span className="stat-badge">{graphData.nodes.length} {t('nodes')}</span>
                  <span className="stat-badge">{graphData.edges.length} {t('edges')}</span>
                </div>
              )}
            </div>

            {/* Data Viewer */}
            {graphData && (
              <div className="data-viewer">
                <div className="data-viewer-toolbar">
                  <div className="toolbar-left">
                    <h3>{selectedClass ? shortenUri(selectedClass) : t('allClasses')}</h3>
                    <span className="instance-count">
                      {filteredNodes.length} {t('nodes')}
                    </span>
                  </div>
                  <div className="toolbar-right">
                    <input
                      type="text"
                      className="search-input"
                      placeholder={t('search')}
                      value={searchTerm}
                      onChange={(e) => setSearchTerm(e.target.value)}
                    />
                    <div className="view-toggle">
                      <button
                        className={`toggle-btn ${exploreViewMode === 'graph' ? 'active' : ''}`}
                        onClick={() => setExploreViewMode('graph')}
                      >
                        {t('graphView')}
                      </button>
                      <button
                        className={`toggle-btn ${exploreViewMode === 'table' ? 'active' : ''}`}
                        onClick={() => setExploreViewMode('table')}
                      >
                        {t('tableView')}
                      </button>
                    </div>
                  </div>
                </div>

                {isLoadingData ? (
                  <div className="loading-container">
                    <div className="loading-spinner" />
                    <p>{t('loading')}</p>
                  </div>
                ) : !graphData?.nodes.length ? (
                  <p className="empty-message">{t('noData')}</p>
                ) : exploreViewMode === 'graph' ? (
                  <div className="graph-container">
                    <OxigraphGraphVisualization
                      data={{ nodes: filteredNodes, edges: graphData.edges }}
                      width={800}
                      height={500}
                      onNodeClick={setSelectedNode}
                    />
                  </div>
                ) : (
                  <div className="table-container">
                    <table className="data-table">
                      <thead>
                        <tr>
                          <th>URI</th>
                          <th>Label</th>
                          <th>Type</th>
                        </tr>
                      </thead>
                      <tbody>
                        {filteredNodes.map(node => (
                          <tr
                            key={node.id}
                            onClick={() => setSelectedNode(node)}
                            className={selectedNode?.id === node.id ? 'selected' : ''}
                          >
                            <td><code title={node.id}>{shortenUri(node.id)}</code></td>
                            <td>{node.label}</td>
                            <td>{node.entityType}</td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                )}

                {/* Node Detail Panel */}
                {selectedNode && (
                  <div className="node-detail-panel">
                    <div className="node-detail-header">
                      <h4>{selectedNode.label}</h4>
                      <button className="close-btn" onClick={() => setSelectedNode(null)}>×</button>
                    </div>
                    <div className="node-detail-content">
                      <p><strong>URI:</strong> <code>{selectedNode.id}</code></p>
                      <p><strong>Type:</strong> {selectedNode.entityType}</p>
                    </div>
                  </div>
                )}
              </div>
            )}

            {!graphData && !isLoadingData && (
              <p className="help-text">Select a class and click "Load Graph" to visualize RDF data</p>
            )}
          </div>
        )}

        {activeTab === 'graphs' && (
          <div className="graphs-list">
            {!stats?.graphs.length ? (
              <p className="empty-message">{t('noData')}</p>
            ) : (
              <>
                <div className="action-bar">
                  <button onClick={() => handleExport()} className="secondary-button">
                    {t('export')} Default Graph
                  </button>
                  <button onClick={handleClearAll} className="danger-button">
                    {t('clearAll')}
                  </button>
                </div>
                <table className="data-table">
                  <thead>
                    <tr>
                      <th>{t('graphName')}</th>
                      <th>{t('tripleCount')}</th>
                      <th>Actions</th>
                    </tr>
                  </thead>
                  <tbody>
                    {stats.graphs.map((graph, index) => (
                      <tr key={index}>
                        <td><code title={graph.name}>{shortenUri(graph.name)}</code></td>
                        <td>{graph.tripleCount.toLocaleString()}</td>
                        <td>
                          <button
                            className="small-button"
                            onClick={() => handleExport(graph.name === '(default graph)' ? undefined : graph.name)}
                          >
                            {t('export')}
                          </button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </>
            )}
          </div>
        )}

        {activeTab === 'classes' && (
          <div className="classes-list">
            {!stats?.classes.length ? (
              <p className="empty-message">{t('noData')}</p>
            ) : (
              <table className="data-table">
                <thead>
                  <tr>
                    <th>{t('class')}</th>
                    <th>{t('count')}</th>
                  </tr>
                </thead>
                <tbody>
                  {stats.classes.map((cls, index) => (
                    <tr key={index}>
                      <td><code title={cls.class}>{shortenUri(cls.class)}</code></td>
                      <td>{cls.count.toLocaleString()}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </div>
        )}

        {activeTab === 'predicates' && (
          <div className="predicates-list">
            {!stats?.predicates.length ? (
              <p className="empty-message">{t('noData')}</p>
            ) : (
              <table className="data-table">
                <thead>
                  <tr>
                    <th>{t('predicate')}</th>
                    <th>{t('count')}</th>
                  </tr>
                </thead>
                <tbody>
                  {stats.predicates.map((pred, index) => (
                    <tr key={index}>
                      <td><code title={pred.predicate}>{shortenUri(pred.predicate)}</code></td>
                      <td>{pred.count.toLocaleString()}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </div>
        )}

        {activeTab === 'namespaces' && (
          <div className="namespaces-list">
            {!stats?.namespaces.length ? (
              <p className="empty-message">{t('noData')}</p>
            ) : (
              <table className="data-table">
                <thead>
                  <tr>
                    <th>{t('prefix')}</th>
                    <th>{t('namespace')}</th>
                    <th>{t('count')}</th>
                  </tr>
                </thead>
                <tbody>
                  {stats.namespaces.map((ns, index) => (
                    <tr key={index}>
                      <td><strong>{ns.prefix}</strong></td>
                      <td><code className="namespace-uri">{ns.namespace}</code></td>
                      <td>{ns.count.toLocaleString()}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </div>
        )}

        {activeTab === 'query' && (
          <div className="query-section">
            <textarea
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              className="query-input"
              rows={6}
              placeholder={t('enterQuery')}
            />
            <button
              onClick={handleRunQuery}
              disabled={isQueryRunning || !status.isConnected}
              className="primary-button"
            >
              {isQueryRunning ? t('running') : t('runQuery')}
            </button>
            {queryResult && <pre className="query-result">{queryResult}</pre>}
          </div>
        )}

        {activeTab === 'upload' && (
          <div className="upload-section">
            <p>{t('uploadDescription')}</p>
            <div className="form-group">
              <label>{t('rdfFormat')}:</label>
              <select
                value={uploadFormat}
                onChange={(e) => setUploadFormat(e.target.value)}
                className="format-select"
              >
                <option value="ttl">Turtle (.ttl)</option>
                <option value="nt">N-Triples (.nt)</option>
                <option value="rdf">RDF/XML (.rdf, .owl)</option>
                <option value="jsonld">JSON-LD (.jsonld)</option>
                <option value="trig">TriG (.trig)</option>
                <option value="nq">N-Quads (.nq)</option>
              </select>
            </div>
            <div className="form-group">
              <label>{t('targetGraph')}:</label>
              <input
                type="text"
                value={uploadGraph}
                onChange={(e) => setUploadGraph(e.target.value)}
                placeholder="https://example.org/graph/my-data"
                className="text-input"
              />
            </div>
            <div className="form-group">
              <label>File:</label>
              <input
                type="file"
                ref={fileInputRef}
                onChange={handleFileUpload}
                accept=".ttl,.nt,.rdf,.owl,.jsonld,.json,.n3,.trig,.nq"
                className="file-input"
              />
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
