/**
 * Diagnostics.jsx — System diagnostics panel with hardware status monitoring
 *
 * Features:
 *   - Subscribes to /diagnostics (diagnostic_msgs/DiagnosticArray)
 *   - Hardware status cards per subsystem (color-coded health)
 *   - Real-time error and warning counts
 *   - Diagnostic status timeline
 *   - Error/warning history with timestamps
 *   - Aggregated system health summary
 *   - Status indicators: OK (green), WARNING (yellow), ERROR (red), STALE (gray)
 */

import { useEffect, useRef, useState } from 'react';

const MAX_HISTORY = 100; // Keep last 100 diagnostic messages
const STATUS_COLORS = {
  0: { bg: 'bg-green-950', border: 'border-green-800', text: 'text-green-400', label: 'OK' },
  1: { bg: 'bg-yellow-950', border: 'border-yellow-800', text: 'text-yellow-400', label: 'WARN' },
  2: { bg: 'bg-red-950', border: 'border-red-800', text: 'text-red-400', label: 'ERROR' },
  3: { bg: 'bg-gray-900', border: 'border-gray-700', text: 'text-gray-400', label: 'STALE' },
};

function getStatusColor(level) {
  return STATUS_COLORS[level] || STATUS_COLORS[3];
}

function formatTimestamp(timestamp) {
  const date = new Date(timestamp);
  return date.toLocaleTimeString('en-US', {
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
  });
}

function DiagnosticCard({ diagnostic, expanded, onToggle }) {
  const color = getStatusColor(diagnostic.level);

  return (
    <div
      className={`rounded-lg border p-3 space-y-2 cursor-pointer transition-all ${
        color.bg
      } ${color.border} ${expanded ? 'ring-2 ring-offset-2 ring-cyan-500' : ''}`}
      onClick={onToggle}
    >
      {/* Header */}
      <div className="flex items-start justify-between gap-2">
        <div className="flex-1 min-w-0">
          <div className="text-xs font-bold text-gray-400 truncate">{diagnostic.name}</div>
          <div className={`text-sm font-mono font-bold ${color.text}`}>
            {diagnostic.message}
          </div>
        </div>
        <div
          className={`px-2 py-1 rounded text-xs font-bold whitespace-nowrap flex-shrink-0 ${
            color.bg
          } ${color.border} border ${color.text}`}
        >
          {color.label}
        </div>
      </div>

      {/* Expanded details */}
      {expanded && (
        <div className="border-t border-gray-700 pt-2 space-y-2 text-xs">
          {diagnostic.values && diagnostic.values.length > 0 && (
            <div className="space-y-1">
              <div className="text-gray-500 font-bold">KEY VALUES:</div>
              {diagnostic.values.slice(0, 5).map((val, i) => (
                <div key={i} className="flex justify-between gap-2 text-gray-400">
                  <span className="font-mono truncate">{val.key}:</span>
                  <span className="font-mono text-gray-300 truncate">{val.value}</span>
                </div>
              ))}
              {diagnostic.values.length > 5 && (
                <div className="text-gray-500">+{diagnostic.values.length - 5} more values</div>
              )}
            </div>
          )}
          {diagnostic.hardware_id && (
            <div className="text-gray-500">
              <span className="font-bold">Hardware:</span> {diagnostic.hardware_id}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

function HealthTimeline({ statusHistory, maxEntries = 20 }) {
  const recentHistory = statusHistory.slice(-maxEntries);

  return (
    <div className="space-y-2">
      <div className="text-xs font-bold text-gray-400 tracking-widest">TIMELINE</div>
      <div className="space-y-1">
        {recentHistory.map((entry, i) => {
          const color = getStatusColor(entry.level);
          return (
            <div key={i} className="flex items-center gap-2">
              <div className="text-xs text-gray-500 font-mono whitespace-nowrap">
                {formatTimestamp(entry.timestamp)}
              </div>
              <div className={`w-2 h-2 rounded-full flex-shrink-0 ${color.text}`} />
              <div className="text-xs text-gray-400 truncate">
                {entry.name}: {entry.message}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

export function Diagnostics({ subscribe }) {
  const [diagnostics, setDiagnostics] = useState({});
  const [statusHistory, setStatusHistory] = useState([]);
  const [expandedDiags, setExpandedDiags] = useState(new Set());
  const diagRef = useRef({});

  // Subscribe to diagnostics
  useEffect(() => {
    const unsubscribe = subscribe(
      '/diagnostics',
      'diagnostic_msgs/DiagnosticArray',
      (msg) => {
        try {
          const diags = {};
          const now = Date.now();

          // Process each diagnostic status
          (msg.status || []).forEach((status) => {
            const name = status.name || 'unknown';
            diags[name] = {
              name,
              level: status.level,
              message: status.message || '',
              hardware_id: status.hardware_id || '',
              values: status.values || [],
              timestamp: now,
            };

            // Add to history
            setStatusHistory((prev) => [
              ...prev,
              {
                name,
                level: status.level,
                message: status.message || '',
                timestamp: now,
              },
            ].slice(-MAX_HISTORY));
          });

          setDiagnostics(diags);
          diagRef.current = diags;
        } catch (e) {
          console.error('Error parsing diagnostics:', e);
        }
      }
    );

    return unsubscribe;
  }, [subscribe]);

  // Calculate statistics
  const stats = {
    total: Object.keys(diagnostics).length,
    ok: Object.values(diagnostics).filter((d) => d.level === 0).length,
    warning: Object.values(diagnostics).filter((d) => d.level === 1).length,
    error: Object.values(diagnostics).filter((d) => d.level === 2).length,
    stale: Object.values(diagnostics).filter((d) => d.level === 3).length,
  };

  const overallHealth =
    stats.error > 0 ? 2 : stats.warning > 0 ? 1 : stats.stale > 0 ? 3 : 0;
  const overallColor = getStatusColor(overallHealth);

  const sortedDiags = Object.values(diagnostics).sort((a, b) => {
    // Sort by level (errors first), then by name
    if (a.level !== b.level) return b.level - a.level;
    return a.name.localeCompare(b.name);
  });

  const toggleExpanded = (name) => {
    const updated = new Set(expandedDiags);
    if (updated.has(name)) {
      updated.delete(name);
    } else {
      updated.add(name);
    }
    setExpandedDiags(updated);
  };

  return (
    <div className="flex flex-col h-full space-y-3">
      {/* Health Summary */}
      <div className={`rounded-lg border p-3 space-y-3 ${overallColor.bg} ${overallColor.border}`}>
        <div className="flex justify-between items-center">
          <div className={`text-xs font-bold tracking-widest ${overallColor.text}`}>
            SYSTEM HEALTH
          </div>
          <div className={`text-xs font-bold px-3 py-1 rounded ${overallColor.text}`}>
            {overallColor.label}
          </div>
        </div>

        {/* Stats Grid */}
        <div className="grid grid-cols-5 gap-2">
          <div className="bg-gray-900 rounded p-2">
            <div className="text-gray-600 text-xs">TOTAL</div>
            <div className="text-lg font-mono text-cyan-300 font-bold">{stats.total}</div>
          </div>
          <div className="bg-green-950 rounded p-2">
            <div className="text-gray-600 text-xs">OK</div>
            <div className="text-lg font-mono text-green-400 font-bold">{stats.ok}</div>
          </div>
          <div className="bg-yellow-950 rounded p-2">
            <div className="text-gray-600 text-xs">WARN</div>
            <div className="text-lg font-mono text-yellow-400 font-bold">{stats.warning}</div>
          </div>
          <div className="bg-red-950 rounded p-2">
            <div className="text-gray-600 text-xs">ERROR</div>
            <div className="text-lg font-mono text-red-400 font-bold">{stats.error}</div>
          </div>
          <div className="bg-gray-900 rounded p-2">
            <div className="text-gray-600 text-xs">STALE</div>
            <div className="text-lg font-mono text-gray-400 font-bold">{stats.stale}</div>
          </div>
        </div>
      </div>

      {/* Diagnostics Grid */}
      <div className="flex-1 overflow-y-auto space-y-2">
        {sortedDiags.length === 0 ? (
          <div className="flex items-center justify-center h-32 text-gray-600">
            <div className="text-center">
              <div className="text-sm mb-2">Waiting for diagnostics</div>
              <div className="text-xs text-gray-700">
                Messages from /diagnostics will appear here
              </div>
            </div>
          </div>
        ) : (
          sortedDiags.map((diag) => (
            <DiagnosticCard
              key={diag.name}
              diagnostic={diag}
              expanded={expandedDiags.has(diag.name)}
              onToggle={() => toggleExpanded(diag.name)}
            />
          ))
        )}
      </div>

      {/* Timeline and Info */}
      <div className="grid grid-cols-2 gap-2">
        {/* Timeline */}
        <div className="bg-gray-950 rounded-lg border border-cyan-950 p-3">
          <HealthTimeline statusHistory={statusHistory} maxEntries={10} />
        </div>

        {/* Legend */}
        <div className="bg-gray-950 rounded-lg border border-cyan-950 p-3 space-y-2">
          <div className="text-xs font-bold text-gray-400 tracking-widest mb-2">STATUS LEGEND</div>
          <div className="space-y-1 text-xs">
            <div className="flex items-center gap-2">
              <div className="w-2 h-2 rounded-full bg-green-500" />
              <span className="text-gray-400">OK — System nominal</span>
            </div>
            <div className="flex items-center gap-2">
              <div className="w-2 h-2 rounded-full bg-yellow-500" />
              <span className="text-gray-400">WARN — Check required</span>
            </div>
            <div className="flex items-center gap-2">
              <div className="w-2 h-2 rounded-full bg-red-500" />
              <span className="text-gray-400">ERROR — Immediate action</span>
            </div>
            <div className="flex items-center gap-2">
              <div className="w-2 h-2 rounded-full bg-gray-500" />
              <span className="text-gray-400">STALE — No recent data</span>
            </div>
          </div>
        </div>
      </div>

      {/* Topic Info */}
      <div className="bg-gray-950 rounded border border-gray-800 p-2 text-xs text-gray-600 space-y-1">
        <div className="flex justify-between">
          <span>Topic:</span>
          <span className="text-gray-500">/diagnostics (diagnostic_msgs/DiagnosticArray)</span>
        </div>
        <div className="flex justify-between">
          <span>Status Levels:</span>
          <span className="text-gray-500">0=OK, 1=WARN, 2=ERROR, 3=STALE</span>
        </div>
        <div className="flex justify-between">
          <span>History Limit:</span>
          <span className="text-gray-500">{MAX_HISTORY} events</span>
        </div>
      </div>
    </div>
  );
}
