/**
 * EventLog.jsx — Robot event log viewer
 *
 * Displays timestamped, color-coded event cards from:
 *   /saltybot/emergency        (emergency events)
 *   /saltybot/docking_status   (docking state changes)
 *   /diagnostics               (system diagnostics)
 *
 * Features:
 *   - Real-time event streaming
 *   - Color-coded by event type (red=emergency, blue=docking, cyan=diagnostics)
 *   - Filter by type
 *   - Auto-scroll to latest event
 *   - Configurable max event history (default 200)
 */

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

const EVENT_TYPES = {
  EMERGENCY: 'emergency',
  DOCKING: 'docking',
  DIAGNOSTIC: 'diagnostic',
};

const EVENT_COLORS = {
  emergency: { bg: 'bg-red-950', border: 'border-red-800', text: 'text-red-400', label: 'Emergency' },
  docking: { bg: 'bg-blue-950', border: 'border-blue-800', text: 'text-blue-400', label: 'Docking' },
  diagnostic: { bg: 'bg-cyan-950', border: 'border-cyan-800', text: 'text-cyan-400', label: 'Diagnostic' },
};

const MAX_EVENTS = 200;

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

function EventCard({ event, colors }) {
  return (
    <div className={`rounded border ${colors.border} ${colors.bg} p-3 text-sm space-y-1`}>
      <div className="flex justify-between items-start gap-2">
        <span className={`font-bold tracking-widest text-xs ${colors.text}`}>
          {colors.label}
        </span>
        <span className="text-gray-600 text-xs flex-shrink-0">
          {formatTimestamp(event.timestamp)}
        </span>
      </div>
      <div className="text-gray-300 break-words">
        {event.message}
      </div>
      {event.details && (
        <div className="text-gray-500 text-xs font-mono pt-1 border-t border-gray-800">
          {typeof event.details === 'string' ? (
            event.details
          ) : (
            <pre className="overflow-x-auto">{JSON.stringify(event.details, null, 2)}</pre>
          )}
        </div>
      )}
    </div>
  );
}

export function EventLog({ subscribe }) {
  const [events, setEvents] = useState([]);
  const [selectedTypes, setSelectedTypes] = useState(new Set(Object.values(EVENT_TYPES)));
  const [expandedEventId, setExpandedEventId] = useState(null);
  const scrollRef = useRef(null);
  const eventIdRef = useRef(0);

  // Auto-scroll to bottom when new events arrive
  useEffect(() => {
    if (scrollRef.current && events.length > 0) {
      setTimeout(() => {
        scrollRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' });
      }, 0);
    }
  }, [events.length]);

  // Subscribe to emergency events
  useEffect(() => {
    const unsub = subscribe(
      '/saltybot/emergency',
      'std_msgs/String',
      (msg) => {
        try {
          const data = typeof msg.data === 'string' ? JSON.parse(msg.data) : msg.data;
          setEvents((prev) => [
            ...prev,
            {
              id: ++eventIdRef.current,
              type: EVENT_TYPES.EMERGENCY,
              timestamp: Date.now(),
              message: data.message || data.status || JSON.stringify(data),
              details: data,
            },
          ].slice(-MAX_EVENTS));
        } catch (e) {
          setEvents((prev) => [
            ...prev,
            {
              id: ++eventIdRef.current,
              type: EVENT_TYPES.EMERGENCY,
              timestamp: Date.now(),
              message: msg.data || 'Unknown emergency event',
              details: null,
            },
          ].slice(-MAX_EVENTS));
        }
      }
    );
    return unsub;
  }, [subscribe]);

  // Subscribe to docking status
  useEffect(() => {
    const unsub = subscribe(
      '/saltybot/docking_status',
      'std_msgs/String',
      (msg) => {
        try {
          const data = typeof msg.data === 'string' ? JSON.parse(msg.data) : msg.data;
          const statusMsg = data.status || data.state || data.message || JSON.stringify(data);
          setEvents((prev) => [
            ...prev,
            {
              id: ++eventIdRef.current,
              type: EVENT_TYPES.DOCKING,
              timestamp: Date.now(),
              message: `Docking Status: ${statusMsg}`,
              details: data,
            },
          ].slice(-MAX_EVENTS));
        } catch (e) {
          setEvents((prev) => [
            ...prev,
            {
              id: ++eventIdRef.current,
              type: EVENT_TYPES.DOCKING,
              timestamp: Date.now(),
              message: `Docking Status: ${msg.data || 'Unknown'}`,
              details: null,
            },
          ].slice(-MAX_EVENTS));
        }
      }
    );
    return unsub;
  }, [subscribe]);

  // Subscribe to diagnostics
  useEffect(() => {
    const unsub = subscribe(
      '/diagnostics',
      'diagnostic_msgs/DiagnosticArray',
      (msg) => {
        try {
          for (const status of msg.status ?? []) {
            if (status.level > 0) {
              // Only log warnings and errors
              const kv = {};
              for (const pair of status.values ?? []) {
                kv[pair.key] = pair.value;
              }
              setEvents((prev) => [
                ...prev,
                {
                  id: ++eventIdRef.current,
                  type: EVENT_TYPES.DIAGNOSTIC,
                  timestamp: Date.now(),
                  message: `${status.name}: ${status.message}`,
                  details: kv,
                },
              ].slice(-MAX_EVENTS));
            }
          }
        } catch (e) {
          // Ignore parsing errors
        }
      }
    );
    return unsub;
  }, [subscribe]);

  const filteredEvents = events.filter((event) => selectedTypes.has(event.type));

  const toggleEventType = (type) => {
    setSelectedTypes((prev) => {
      const next = new Set(prev);
      if (next.has(type)) {
        next.delete(type);
      } else {
        next.add(type);
      }
      return next;
    });
  };

  const clearEvents = () => {
    setEvents([]);
    eventIdRef.current = 0;
  };

  return (
    <div className="flex flex-col h-full space-y-3">
      {/* Controls */}
      <div className="bg-gray-950 rounded-lg border border-cyan-950 p-4 space-y-3">
        <div className="flex justify-between items-center flex-wrap gap-2">
          <div className="text-cyan-700 text-xs font-bold tracking-widest">
            EVENT LOG
          </div>
          <div className="text-gray-600 text-xs">
            {filteredEvents.length} of {events.length} events
          </div>
        </div>

        {/* Filter buttons */}
        <div className="flex gap-2 flex-wrap">
          {Object.entries(EVENT_COLORS).map(([typeKey, colors]) => (
            <button
              key={typeKey}
              onClick={() => toggleEventType(typeKey)}
              className={`px-3 py-1.5 text-xs font-bold tracking-widest rounded border transition-colors ${
                selectedTypes.has(typeKey)
                  ? `${colors.bg} ${colors.border} ${colors.text}`
                  : 'bg-gray-900 border-gray-800 text-gray-600 hover:text-gray-400'
              }`}
            >
              {colors.label}
            </button>
          ))}
          <button
            onClick={clearEvents}
            className="ml-auto px-3 py-1.5 text-xs font-bold tracking-widest rounded border border-gray-800 text-gray-600 hover:text-red-400 hover:border-red-800 transition-colors"
          >
            CLEAR
          </button>
        </div>
      </div>

      {/* Event list */}
      <div className="flex-1 overflow-y-auto space-y-2 pr-2">
        {filteredEvents.length > 0 ? (
          <>
            {filteredEvents.map((event) => {
              const colors = EVENT_COLORS[event.type];
              return (
                <div
                  key={event.id}
                  onClick={() =>
                    setExpandedEventId(expandedEventId === event.id ? null : event.id)
                  }
                  className="cursor-pointer hover:opacity-80 transition-opacity"
                >
                  <EventCard event={event} colors={colors} />
                </div>
              );
            })}
            <div ref={scrollRef} />
          </>
        ) : (
          <div className="text-center py-12 text-gray-600 text-sm">
            {events.length === 0 ? (
              <>
                <div>No events yet</div>
                <div className="text-xs text-gray-700 mt-2">
                  Waiting for events from emergency, docking, and diagnostics topics…
                </div>
              </>
            ) : (
              <>
                <div>No events match selected filter</div>
                <div className="text-xs text-gray-700 mt-2">
                  {events.length} events available, adjust filters above
                </div>
              </>
            )}
          </div>
        )}
      </div>

      {/* Stats footer */}
      <div className="bg-gray-950 rounded border border-gray-800 p-2 text-xs text-gray-600 flex justify-between">
        <span>Displaying {filteredEvents.length} / {events.length} events</span>
        <span className="text-gray-700">Max capacity: {MAX_EVENTS}</span>
      </div>
    </div>
  );
}
