/**
 * AuditLogsPanel - ZCLAW Audit Logs UI with Merkle Hash Chain Verification
 *
 * Phase 3.4 Enhancement: Full-featured audit log viewer with:
 * - Complete log entry display
 * - Merkle hash chain verification
 * - Export functionality (JSON/CSV)
 * - Search and filter capabilities
 * - Real-time log streaming
 */

import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import {
  Search,
  Filter,
  FileJson,
  FileSpreadsheet,
  ChevronDown,
  ChevronUp,
  Hash,
  Link,
  CheckCircle2,
  XCircle,
  AlertCircle,
  RefreshCw,
  Pause,
  Play,
  X,
  Loader2
} from 'lucide-react';
import { useSecurityStore, AuditLogEntry } from '../store/securityStore';
import { getClient } from '../store/connectionStore';

// === Types ===

export interface MerkleVerificationResult {
  valid: boolean;
  chainDepth: number;
  rootHash: string;
  previousHash: string;
  currentHash: string;
  brokenAtIndex?: number;
}

export interface AuditLogFilter {
  timeRange?: { start: Date; end: Date };
  eventTypes?: string[];
  actors?: string[];
  searchTerm?: string;
  result?: 'success' | 'failure' | 'all';
}

interface EnhancedAuditLogEntry extends AuditLogEntry {
  // Extended fields from ZCLAW
  targetResource?: string;
  operationDetails?: Record<string, unknown>;
  ipAddress?: string;
  sessionId?: string;
  // Merkle chain fields
  hash?: string;
  previousHash?: string;
  chainIndex?: number;
}

// === Helper Functions ===

function formatTimestamp(timestamp: string): string {
  try {
    const date = new Date(timestamp);
    return date.toLocaleString('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
    });
  } catch {
    return timestamp;
  }
}

function formatHash(hash: string | undefined): string {
  if (!hash) return '-';
  if (hash.length <= 16) return hash;
  return `${hash.slice(0, 8)}...${hash.slice(-8)}`;
}

function truncateText(text: string | undefined, maxLength: number = 30): string {
  if (!text) return '-';
  if (text.length <= maxLength) return text;
  return `${text.slice(0, maxLength)}...`;
}

// === Export Functions ===

function exportToJSON(logs: EnhancedAuditLogEntry[]): string {
  const exportData = logs.map(log => ({
    id: log.id,
    timestamp: log.timestamp,
    action: log.action,
    actor: log.actor || null,
    result: log.result || null,
    targetResource: log.targetResource || null,
    details: log.details || null,
    ipAddress: log.ipAddress || null,
    sessionId: log.sessionId || null,
    hash: log.hash || null,
    previousHash: log.previousHash || null,
  }));
  return JSON.stringify(exportData, null, 2);
}

function exportToCSV(logs: EnhancedAuditLogEntry[]): string {
  const headers = [
    'ID',
    'Timestamp',
    'Action',
    'Actor',
    'Result',
    'Target Resource',
    'IP Address',
    'Session ID',
    'Hash',
    'Previous Hash'
  ];

  const rows = logs.map(log => [
    log.id,
    log.timestamp,
    `"${(log.action || '').replace(/"/g, '""')}"`,
    `"${(log.actor || '').replace(/"/g, '""')}"`,
    log.result || '',
    `"${(log.targetResource || '').replace(/"/g, '""')}"`,
    log.ipAddress || '',
    log.sessionId || '',
    log.hash || '',
    log.previousHash || '',
  ].join(','));

  return [headers.join(','), ...rows].join('\n');
}

function downloadFile(content: string, filename: string, mimeType: string): void {
  const blob = new Blob([content], { type: mimeType });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(url);
}

// === Sub-Components ===

interface FilterPanelProps {
  filter: AuditLogFilter;
  onFilterChange: (filter: AuditLogFilter) => void;
  eventTypes: string[];
  actors: string[];
  onReset: () => void;
}

function FilterPanel({ filter, onFilterChange, eventTypes, actors, onReset }: FilterPanelProps) {
  // Helper to safely create time range with proper null handling
  const handleStartTimeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const newStart = e.target.value ? new Date(e.target.value) : undefined;
    const currentEnd = filter.timeRange?.end;
    onFilterChange({
      ...filter,
      timeRange: (newStart || currentEnd) ? { start: newStart!, end: currentEnd! } : undefined,
    });
  };

  const handleEndTimeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const newEnd = e.target.value ? new Date(e.target.value) : undefined;
    const currentStart = filter.timeRange?.start;
    onFilterChange({
      ...filter,
      timeRange: (currentStart || newEnd) ? { start: currentStart!, end: newEnd! } : undefined,
    });
  };

  return (
    <div className="space-y-3 p-4 bg-gray-50 dark:bg-gray-800/50 rounded-lg">
      {/* Time Range */}
      <div>
        <label className="block text-xs font-medium text-gray-600 dark:text-gray-400 mb-1">
          Time Range
        </label>
        <div className="flex gap-2">
          <input
            type="datetime-local"
            value={filter.timeRange?.start?.toISOString().slice(0, 16) || ''}
            onChange={handleStartTimeChange}
            className="flex-1 text-xs px-2 py-1 border border-gray-200 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300"
            placeholder="Start"
          />
          <input
            type="datetime-local"
            value={filter.timeRange?.end?.toISOString().slice(0, 16) || ''}
            onChange={handleEndTimeChange}
            className="flex-1 text-xs px-2 py-1 border border-gray-200 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300"
            placeholder="End"
          />
        </div>
      </div>

      {/* Event Type */}
      <div>
        <label className="block text-xs font-medium text-gray-600 dark:text-gray-400 mb-1">
          Event Type
        </label>
        <select
          multiple
          value={filter.eventTypes || []}
          onChange={(e) => onFilterChange({
            ...filter,
            eventTypes: Array.from(e.target.selectedOptions, (opt) => opt.value),
          })}
          className="w-full text-xs px-2 py-1 border border-gray-200 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300"
          size={3}
        >
          {eventTypes.map((type) => (
            <option key={type} value={type}>
              {type}
            </option>
          ))}
        </select>
      </div>

      {/* Actor */}
      <div>
        <label className="block text-xs font-medium text-gray-600 dark:text-gray-400 mb-1">
          Actor
        </label>
        <select
          multiple
          value={filter.actors || []}
          onChange={(e) => onFilterChange({
            ...filter,
            actors: Array.from(e.target.selectedOptions, (opt) => opt.value),
          })}
          className="w-full text-xs px-2 py-1 border border-gray-200 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300"
          size={3}
        >
          {actors.map((actor) => (
            <option key={actor} value={actor}>
              {actor}
            </option>
          ))}
        </select>
      </div>

      {/* Result */}
      <div>
        <label className="block text-xs font-medium text-gray-600 dark:text-gray-400 mb-1">
          Result
        </label>
        <select
          value={filter.result || 'all'}
          onChange={(e) => onFilterChange({
            ...filter,
            result: e.target.value === 'all' ? undefined : e.target.value as 'success' | 'failure',
          })}
          className="w-full text-xs px-2 py-1 border border-gray-200 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300"
        >
          <option value="all">All</option>
          <option value="success">Success</option>
          <option value="failure">Failure</option>
        </select>
      </div>

      {/* Reset Button */}
      <button
        onClick={onReset}
        className="w-full text-xs px-3 py-1.5 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors"
      >
        Reset Filters
      </button>
    </div>
  );
}

interface LogDetailSidebarProps {
  log: EnhancedAuditLogEntry | null;
  onClose: () => void;
  onVerify: (log: EnhancedAuditLogEntry) => void;
  verificationResult: MerkleVerificationResult | null;
  isVerifying: boolean;
}

function LogDetailSidebar({
  log,
  onClose,
  onVerify,
  verificationResult,
  isVerifying,
}: LogDetailSidebarProps) {
  if (!log) return null;

  return (
    <div className="w-80 border-l border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-4 overflow-y-auto">
      <div className="flex items-center justify-between mb-4">
        <h3 className="text-sm font-semibold text-gray-900 dark:text-white">Log Details</h3>
        <button
          onClick={onClose}
          className="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
        >
          <X className="w-4 h-4" />
        </button>
      </div>

      <div className="space-y-3">
        {/* Timestamp */}
        <div>
          <span className="block text-xs font-medium text-gray-500 dark:text-gray-400">Timestamp</span>
          <span className="text-sm text-gray-900 dark:text-white">{formatTimestamp(log.timestamp)}</span>
        </div>

        {/* Action */}
        <div>
          <span className="block text-xs font-medium text-gray-500 dark:text-gray-400">Action</span>
          <span className="text-sm text-gray-900 dark:text-white">{log.action}</span>
        </div>

        {/* Actor */}
        <div>
          <span className="block text-xs font-medium text-gray-500 dark:text-gray-400">Actor</span>
          <span className="text-sm text-gray-900 dark:text-white">{log.actor || '-'}</span>
        </div>

        {/* Result */}
        <div>
          <span className="block text-xs font-medium text-gray-500 dark:text-gray-400">Result</span>
          <span className={`inline-flex items-center gap-1 text-sm ${
            log.result === 'success' ? 'text-green-600' : log.result === 'failure' ? 'text-red-600' : 'text-gray-600'
          }`}>
            {log.result === 'success' ? (
              <CheckCircle2 className="w-4 h-4" />
            ) : log.result === 'failure' ? (
              <XCircle className="w-4 h-4" />
            ) : null}
            {log.result || '-'}
          </span>
        </div>

        {/* Target Resource */}
        {log.targetResource && (
          <div>
            <span className="block text-xs font-medium text-gray-500 dark:text-gray-400">Target Resource</span>
            <span className="text-sm text-gray-900 dark:text-white break-all">{log.targetResource}</span>
          </div>
        )}

        {/* IP Address */}
        {log.ipAddress && (
          <div>
            <span className="block text-xs font-medium text-gray-500 dark:text-gray-400">IP Address</span>
            <span className="text-sm text-gray-900 dark:text-white font-mono">{log.ipAddress}</span>
          </div>
        )}

        {/* Session ID */}
        {log.sessionId && (
          <div>
            <span className="block text-xs font-medium text-gray-500 dark:text-gray-400">Session ID</span>
            <span className="text-sm text-gray-900 dark:text-white font-mono truncate">{log.sessionId}</span>
          </div>
        )}

        {/* Details */}
        {log.details && Object.keys(log.details).length > 0 && (
          <div>
            <span className="block text-xs font-medium text-gray-500 dark:text-gray-400 mb-1">Details</span>
            <pre className="text-xs bg-gray-100 dark:bg-gray-900 p-2 rounded overflow-x-auto">
              {JSON.stringify(log.details, null, 2)}
            </pre>
          </div>
        )}

        {/* Merkle Hash Section */}
        <div className="border-t border-gray-200 dark:border-gray-700 pt-3 mt-3">
          <h4 className="text-xs font-semibold text-gray-700 dark:text-gray-300 mb-2 flex items-center gap-1">
            <Hash className="w-3.5 h-3.5" />
            Merkle Hash Chain
          </h4>

          {/* Current Hash */}
          <div className="mb-2">
            <span className="block text-xs font-medium text-gray-500 dark:text-gray-400">Current Hash</span>
            <span className="text-xs text-gray-700 dark:text-gray-300 font-mono break-all">
              {log.hash || 'Not available'}
            </span>
          </div>

          {/* Previous Hash */}
          <div className="mb-2">
            <span className="block text-xs font-medium text-gray-500 dark:text-gray-400">Previous Hash</span>
            <span className="text-xs text-gray-700 dark:text-gray-300 font-mono break-all">
              {log.previousHash || 'Not available'}
            </span>
          </div>

          {/* Chain Index */}
          {log.chainIndex !== undefined && (
            <div className="mb-3">
              <span className="block text-xs font-medium text-gray-500 dark:text-gray-400">Chain Index</span>
              <span className="text-xs text-gray-700 dark:text-gray-300">{log.chainIndex}</span>
            </div>
          )}

          {/* Verify Button */}
          <button
            onClick={() => onVerify(log)}
            disabled={isVerifying || !log.hash}
            className="w-full flex items-center justify-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
          >
            {isVerifying ? (
              <Loader2 className="w-3.5 h-3.5 animate-spin" />
            ) : (
              <Link className="w-3.5 h-3.5" />
            )}
            {isVerifying ? 'Verifying...' : 'Verify Chain'}
          </button>

          {/* Verification Result */}
          {verificationResult && (
            <div className={`mt-2 p-2 rounded text-xs ${
              verificationResult.valid
                ? 'bg-green-50 dark:bg-green-900/20 text-green-700 dark:text-green-400'
                : 'bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400'
            }`}>
              <div className="flex items-center gap-1.5 mb-1">
                {verificationResult.valid ? (
                  <CheckCircle2 className="w-3.5 h-3.5" />
                ) : (
                  <XCircle className="w-3.5 h-3.5" />
                )}
                <span className="font-medium">
                  {verificationResult.valid ? 'Chain Valid' : 'Chain Broken'}
                </span>
              </div>
              {!verificationResult.valid && verificationResult.brokenAtIndex !== undefined && (
                <p>Broken at index: {verificationResult.brokenAtIndex}</p>
              )}
              <p className="text-gray-500 dark:text-gray-400">Depth: {verificationResult.chainDepth}</p>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

interface HashChainVisualizationProps {
  logs: EnhancedAuditLogEntry[];
  selectedIndex: number | null;
  onSelect: (index: number) => void;
  brokenAtIndex?: number;
}

function HashChainVisualization({ logs, selectedIndex, onSelect, brokenAtIndex }: HashChainVisualizationProps) {
  const visibleLogs = logs.slice(0, 10); // Show last 10 for visualization

  return (
    <div className="p-3 bg-gray-50 dark:bg-gray-800/50 rounded-lg">
      <h4 className="text-xs font-semibold text-gray-700 dark:text-gray-300 mb-2 flex items-center gap-1">
        <Link className="w-3.5 h-3.5" />
        Hash Chain (Last {visibleLogs.length} entries)
      </h4>
      <div className="flex items-center gap-1 overflow-x-auto pb-1">
        {visibleLogs.map((log, idx) => (
          <div key={log.id} className="flex items-center">
            <button
              onClick={() => onSelect(logs.length - visibleLogs.length + idx)}
              className={`flex-shrink-0 w-6 h-6 rounded flex items-center justify-center text-xs font-mono transition-colors ${
                selectedIndex === logs.length - visibleLogs.length + idx
                  ? 'bg-blue-600 text-white'
                  : brokenAtIndex === logs.length - visibleLogs.length + idx
                  ? 'bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400'
                  : 'bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-300 dark:hover:bg-gray-600'
              }`}
              title={formatTimestamp(log.timestamp)}
            >
              {String(logs.length - visibleLogs.length + idx).padStart(2, '0')}
            </button>
            {idx < visibleLogs.length - 1 && (
              <div className={`w-3 h-0.5 ${
                brokenAtIndex === logs.length - visibleLogs.length + idx
                  ? 'bg-red-400'
                  : 'bg-gray-300 dark:bg-gray-600'
              }`} />
            )}
          </div>
        ))}
      </div>
      {brokenAtIndex !== undefined && (
        <p className="text-xs text-red-600 dark:text-red-400 mt-1">
          <AlertCircle className="w-3.5 h-3.5 inline mr-1" />
          Chain broken at index {brokenAtIndex}
        </p>
      )}
    </div>
  );
}

// === Main Component ===

export function AuditLogsPanel() {
  const auditLogs = useSecurityStore((s) => s.auditLogs);
  const loadAuditLogs = useSecurityStore((s) => s.loadAuditLogs);
  const isLoading = useSecurityStore((s) => s.auditLogsLoading);
  const client = getClient();

  // State
  const [limit, setLimit] = useState(50);
  const [searchTerm, setSearchTerm] = useState('');
  const [showFilters, setShowFilters] = useState(false);
  const [filter, setFilter] = useState<AuditLogFilter>({});
  const [selectedLog, setSelectedLog] = useState<EnhancedAuditLogEntry | null>(null);
  const [verificationResult, setVerificationResult] = useState<MerkleVerificationResult | null>(null);
  const [isVerifying, setIsVerifying] = useState(false);
  const [isStreaming, setIsStreaming] = useState(false);
  const [isPaused, setIsPaused] = useState(false);
  const [chainBrokenAt, setChainBrokenAt] = useState<number | undefined>(undefined);

  const logsEndRef = useRef<HTMLDivElement>(null);
  const streamingRef = useRef<(() => void) | null>(null);

  // Load logs on mount and when limit changes
  useEffect(() => {
    loadAuditLogs({ limit });
  }, [loadAuditLogs, limit]);

  // Auto-scroll to latest when streaming
  useEffect(() => {
    if (isStreaming && !isPaused && logsEndRef.current) {
      logsEndRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [auditLogs, isStreaming, isPaused]);

  // Extract unique event types and actors for filters
  const { eventTypes, actors } = useMemo(() => {
    const types = new Set<string>();
    const actorSet = new Set<string>();

    auditLogs.forEach((log) => {
      if (log.action) types.add(log.action);
      if (log.actor) actorSet.add(log.actor);
    });

    return {
      eventTypes: Array.from(types).sort(),
      actors: Array.from(actorSet).sort(),
    };
  }, [auditLogs]);

  // Filter logs
  const filteredLogs = useMemo(() => {
    let logs = auditLogs as EnhancedAuditLogEntry[];

    // Time range filter
    if (filter.timeRange?.start) {
      const startTime = filter.timeRange.start.getTime();
      logs = logs.filter((log) => new Date(log.timestamp).getTime() >= startTime);
    }
    if (filter.timeRange?.end) {
      const endTime = filter.timeRange.end.getTime();
      logs = logs.filter((log) => new Date(log.timestamp).getTime() <= endTime);
    }

    // Event type filter
    if (filter.eventTypes?.length) {
      logs = logs.filter((log) => filter.eventTypes!.includes(log.action));
    }

    // Actor filter
    if (filter.actors?.length) {
      logs = logs.filter((log) => log.actor && filter.actors!.includes(log.actor));
    }

    // Result filter
    if (filter.result) {
      logs = logs.filter((log) => log.result === filter.result);
    }

    // Search term
    if (searchTerm.trim()) {
      const term = searchTerm.toLowerCase();
      logs = logs.filter((log) =>
        log.action.toLowerCase().includes(term) ||
        (log.actor?.toLowerCase().includes(term)) ||
        (log.details && JSON.stringify(log.details).toLowerCase().includes(term))
      );
    }

    return logs;
  }, [auditLogs, filter, searchTerm]);

  // Real-time streaming setup
  const startStreaming = useCallback(() => {
    if (streamingRef.current) return;

    const unsubscribe = client.on('audit_log', () => {
      if (!isPaused) {
        // Reload logs when new audit log event arrives
        loadAuditLogs({ limit });
      }
    });

    streamingRef.current = unsubscribe;
    setIsStreaming(true);
  }, [client, isPaused, loadAuditLogs, limit]);

  const stopStreaming = useCallback(() => {
    if (streamingRef.current) {
      streamingRef.current();
      streamingRef.current = null;
    }
    setIsStreaming(false);
  }, []);

  const togglePause = useCallback(() => {
    setIsPaused((prev) => !prev);
  }, []);

  // Verify Merkle chain
  const verifyChain = useCallback(async (log: EnhancedAuditLogEntry) => {
    setIsVerifying(true);
    setVerificationResult(null);

    try {
      // Call ZCLAW API to verify the chain (only available on GatewayClient)
      if (!('verifyAuditLogChain' in client)) throw new Error('KernelClient does not support chain verification');
      const result = await client.verifyAuditLogChain(log.id);

      const verification: MerkleVerificationResult = {
        valid: result.valid ?? true,
        chainDepth: result.chain_depth ?? 0,
        rootHash: result.root_hash ?? '',
        previousHash: log.previousHash ?? '',
        currentHash: log.hash ?? '',
        brokenAtIndex: result.broken_at_index,
      };

      setVerificationResult(verification);

      if (!verification.valid && verification.brokenAtIndex !== undefined) {
        setChainBrokenAt(verification.brokenAtIndex);
      }
    } catch {
      // If API not available, do client-side verification
      const logIndex = auditLogs.findIndex((l) => l.id === log.id);
      const previousLog = logIndex > 0 ? (auditLogs[logIndex - 1] as EnhancedAuditLogEntry) : null;

      // Simple verification: check if previous hash matches
      const isValid = !previousLog || log.previousHash === previousLog.hash;

      setVerificationResult({
        valid: isValid,
        chainDepth: logIndex + 1,
        rootHash: (auditLogs[0] as EnhancedAuditLogEntry)?.hash ?? '',
        previousHash: log.previousHash ?? '',
        currentHash: log.hash ?? '',
        brokenAtIndex: isValid ? undefined : logIndex,
      });

      if (!isValid) {
        setChainBrokenAt(logIndex);
      }
    } finally {
      setIsVerifying(false);
    }
  }, [client, auditLogs]);

  // Export handlers
  const handleExportJSON = useCallback(() => {
    const content = exportToJSON(filteredLogs);
    downloadFile(
      content,
      `audit-logs-${new Date().toISOString().slice(0, 10)}.json`,
      'application/json'
    );
  }, [filteredLogs]);

  const handleExportCSV = useCallback(() => {
    const content = exportToCSV(filteredLogs);
    downloadFile(
      content,
      `audit-logs-${new Date().toISOString().slice(0, 10)}.csv`,
      'text/csv'
    );
  }, [filteredLogs]);

  const handleResetFilters = useCallback(() => {
    setFilter({});
    setSearchTerm('');
  }, []);

  const resultColor = {
    success: 'text-green-600 dark:text-green-400',
    failure: 'text-red-600 dark:text-red-400',
  };

  if (isLoading && auditLogs.length === 0) {
    return (
      <div className="flex items-center justify-center h-64">
        <Loader2 className="w-6 h-6 animate-spin text-gray-400" />
        <span className="ml-2 text-gray-500 dark:text-gray-400">Loading...</span>
      </div>
    );
  }

  return (
    <div className="flex h-full">
      {/* Main Content */}
      <div className="flex-1 flex flex-col min-w-0">
        {/* Header */}
        <div className="flex items-center justify-between mb-4">
          <div className="flex items-center gap-3">
            <h2 className="text-lg font-semibold text-gray-900 dark:text-white">
              Audit Logs
            </h2>
            {/* Real-time streaming controls */}
            <div className="flex items-center gap-1">
              {isStreaming ? (
                <>
                  <button
                    onClick={togglePause}
                    className={`p-1.5 rounded transition-colors ${
                      isPaused
                        ? 'bg-yellow-100 dark:bg-yellow-900/30 text-yellow-600'
                        : 'bg-green-100 dark:bg-green-900/30 text-green-600'
                    }`}
                    title={isPaused ? 'Resume' : 'Pause'}
                  >
                    {isPaused ? <Play className="w-4 h-4" /> : <Pause className="w-4 h-4" />}
                  </button>
                  <button
                    onClick={stopStreaming}
                    className="p-1.5 rounded bg-red-100 dark:bg-red-900/30 text-red-600 hover:bg-red-200 dark:hover:bg-red-900/50 transition-colors"
                    title="Stop streaming"
                  >
                    <X className="w-4 h-4" />
                  </button>
                  <span className="text-xs text-green-600 dark:text-green-400 flex items-center gap-1">
                    <span className="w-1.5 h-1.5 bg-green-500 rounded-full animate-pulse" />
                    {isPaused ? 'Paused' : 'Live'}
                  </span>
                </>
              ) : (
                <button
                  onClick={startStreaming}
                  className="flex items-center gap-1 px-2 py-1 text-xs bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 rounded hover:bg-blue-200 dark:hover:bg-blue-900/50 transition-colors"
                >
                  <Play className="w-3.5 h-3.5" />
                  Live Stream
                </button>
              )}
            </div>
          </div>
          <div className="flex items-center gap-2">
            {/* Search */}
            <div className="relative">
              <Search className="w-4 h-4 absolute left-2 top-1/2 transform -translate-y-1/2 text-gray-400" />
              <input
                type="text"
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
                placeholder="Search..."
                className="pl-8 pr-3 py-1.5 text-sm border border-gray-200 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 w-48"
              />
            </div>

            {/* Filter Toggle */}
            <button
              onClick={() => setShowFilters(!showFilters)}
              className={`flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-md transition-colors ${
                showFilters
                  ? 'bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400'
                  : 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600'
              }`}
            >
              <Filter className="w-4 h-4" />
              Filter
              {showFilters ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}
            </button>

            {/* Export */}
            <div className="flex items-center gap-1">
              <button
                onClick={handleExportJSON}
                className="flex items-center gap-1 px-2 py-1.5 text-sm bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 rounded-md hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
                title="Export as JSON"
              >
                <FileJson className="w-4 h-4" />
              </button>
              <button
                onClick={handleExportCSV}
                className="flex items-center gap-1 px-2 py-1.5 text-sm bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 rounded-md hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
                title="Export as CSV"
              >
                <FileSpreadsheet className="w-4 h-4" />
              </button>
            </div>

            {/* Limit selector */}
            <select
              value={limit}
              onChange={(e) => setLimit(Number(e.target.value))}
              className="text-sm border border-gray-200 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 px-2 py-1"
            >
              <option value={25}>25</option>
              <option value={50}>50</option>
              <option value={100}>100</option>
              <option value={200}>200</option>
              <option value={500}>500</option>
            </select>

            {/* Refresh */}
            <button
              onClick={() => loadAuditLogs({ limit })}
              disabled={isLoading}
              className="p-1.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 disabled:opacity-50"
              title="Refresh"
            >
              <RefreshCw className={`w-4 h-4 ${isLoading ? 'animate-spin' : ''}`} />
            </button>
          </div>
        </div>

        {/* Filter Panel */}
        {showFilters && (
          <div className="mb-4">
            <FilterPanel
              filter={filter}
              onFilterChange={setFilter}
              eventTypes={eventTypes}
              actors={actors}
              onReset={handleResetFilters}
            />
          </div>
        )}

        {/* Hash Chain Visualization */}
        {filteredLogs.length > 0 && (
          <div className="mb-4">
            <HashChainVisualization
              logs={filteredLogs}
              selectedIndex={selectedLog ? filteredLogs.findIndex((l) => l.id === selectedLog.id) : null}
              onSelect={(idx) => setSelectedLog(filteredLogs[idx])}
              brokenAtIndex={chainBrokenAt}
            />
          </div>
        )}

        {/* Log Table */}
        <div className="flex-1 overflow-auto">
          {filteredLogs.length === 0 ? (
            <div className="flex flex-col items-center justify-center h-full text-gray-500 dark:text-gray-400">
              <AlertCircle className="w-8 h-8 mb-2" />
              <p>No audit logs found</p>
              {(searchTerm || Object.keys(filter).length > 0) && (
                <button
                  onClick={handleResetFilters}
                  className="mt-2 text-sm text-blue-600 dark:text-blue-400 hover:underline"
                >
                  Clear filters
                </button>
              )}
            </div>
          ) : (
            <table className="w-full text-sm">
              <thead className="sticky top-0 bg-white dark:bg-gray-800 z-10">
                <tr className="border-b border-gray-200 dark:border-gray-700">
                  <th className="text-left py-2 px-3 font-medium text-gray-700 dark:text-gray-300 w-40">Time</th>
                  <th className="text-left py-2 px-3 font-medium text-gray-700 dark:text-gray-300">Action</th>
                  <th className="text-left py-2 px-3 font-medium text-gray-700 dark:text-gray-300 w-32">Actor</th>
                  <th className="text-left py-2 px-3 font-medium text-gray-700 dark:text-gray-300 w-20">Result</th>
                  <th className="text-left py-2 px-3 font-medium text-gray-700 dark:text-gray-300 w-24">Hash</th>
                </tr>
              </thead>
              <tbody>
                {filteredLogs.map((log, index) => (
                  <tr
                    key={log.id || index}
                    onClick={() => setSelectedLog(log)}
                    className={`border-b border-gray-100 dark:border-gray-800 cursor-pointer transition-colors ${
                      selectedLog?.id === log.id
                        ? 'bg-blue-50 dark:bg-blue-900/20'
                        : chainBrokenAt === index
                        ? 'bg-red-50 dark:bg-red-900/10 hover:bg-red-100 dark:hover:bg-red-900/20'
                        : 'hover:bg-gray-50 dark:hover:bg-gray-800/50'
                    }`}
                  >
                    <td className="py-2 px-3 text-gray-600 dark:text-gray-400">
                      {formatTimestamp(log.timestamp)}
                    </td>
                    <td className="py-2 px-3 text-gray-900 dark:text-white">
                      {truncateText(log.action, 40)}
                    </td>
                    <td className="py-2 px-3 text-gray-600 dark:text-gray-400">
                      {truncateText(log.actor, 20)}
                    </td>
                    <td className={`py-2 px-3 ${log.result ? resultColor[log.result] : 'text-gray-600 dark:text-gray-400'}`}>
                      <span className="flex items-center gap-1">
                        {log.result === 'success' ? (
                          <CheckCircle2 className="w-3.5 h-3.5" />
                        ) : log.result === 'failure' ? (
                          <XCircle className="w-3.5 h-3.5" />
                        ) : null}
                        {log.result === 'success' ? 'OK' : log.result === 'failure' ? 'Fail' : '-'}
                      </span>
                    </td>
                    <td className="py-2 px-3 text-gray-500 dark:text-gray-400 font-mono text-xs">
                      {formatHash(log.hash)}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
          <div ref={logsEndRef} />
        </div>

        {/* Stats Footer */}
        <div className="flex items-center justify-between py-2 px-3 border-t border-gray-200 dark:border-gray-700 text-xs text-gray-500 dark:text-gray-400">
          <span>
            Showing {filteredLogs.length} of {auditLogs.length} logs
          </span>
          <span>
            {chainBrokenAt !== undefined && (
              <span className="text-red-600 dark:text-red-400">
                Chain integrity: BROKEN at index {chainBrokenAt}
              </span>
            )}
          </span>
        </div>
      </div>

      {/* Detail Sidebar */}
      {selectedLog && (
        <LogDetailSidebar
          log={selectedLog}
          onClose={() => {
            setSelectedLog(null);
            setVerificationResult(null);
          }}
          onVerify={verifyChain}
          verificationResult={verificationResult}
          isVerifying={isVerifying}
        />
      )}
    </div>
  );
}

export default AuditLogsPanel;
