"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import { Activity, ChevronDown, ChevronRight, Filter, Radio, RefreshCw, X } from "lucide-react";

interface PlatformEvent {
  id: string;
  topic: string;
  from: string;
  payload: unknown;
  ts: number;
}

function TopicBadge({ topic }: { topic: string }) {
  const color = topicColor(topic);
  return (
    <span
      className={`inline-flex items-center rounded px-1.5 py-0.5 text-xs font-mono font-medium ${color}`}
    >
      {topic}
    </span>
  );
}

function topicColor(topic: string): string {
  if (topic.startsWith("deploy.")) return "bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300";
  if (topic.startsWith("perceptor.deploy.")) return "bg-teal-100 text-teal-800 dark:bg-teal-900/30 dark:text-teal-300";
  if (topic.startsWith("backup.")) return "bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-300";
  if (topic.startsWith("service.health.") || topic === "host.down" || topic === "host.up")
    return "bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300";
  if (topic.startsWith("task.")) return "bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300";
  if (topic.startsWith("agent.")) return "bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-300";
  return "bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300";
}

function EventRow({
  event,
  onSelect,
  selected,
}: {
  event: PlatformEvent;
  onSelect: (e: PlatformEvent) => void;
  selected: boolean;
}) {
  const time = new Date(event.ts).toLocaleTimeString([], {
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit",
  });

  return (
    <button
      onClick={() => onSelect(event)}
      className={`flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors ${
        selected
          ? "bg-zinc-100 dark:bg-zinc-800"
          : "hover:bg-zinc-50 dark:hover:bg-zinc-900"
      }`}
    >
      {selected ? (
        <ChevronDown size={14} className="shrink-0 text-zinc-400" />
      ) : (
        <ChevronRight size={14} className="shrink-0 text-zinc-400" />
      )}
      <span className="w-20 shrink-0 text-xs tabular-nums text-zinc-400">{time}</span>
      <span className="shrink-0">
        <TopicBadge topic={event.topic} />
      </span>
      <span className="truncate text-xs text-zinc-500 dark:text-zinc-400">
        from <span className="font-medium text-zinc-700 dark:text-zinc-300">{event.from}</span>
      </span>
    </button>
  );
}

function EventDetail({ event, onClose }: { event: PlatformEvent; onClose: () => void }) {
  const time = new Date(event.ts).toLocaleString();
  const payloadStr =
    typeof event.payload === "string"
      ? event.payload
      : JSON.stringify(event.payload, null, 2);

  return (
    <div className="border-t border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-700 dark:bg-zinc-900">
      <div className="mb-3 flex items-start justify-between gap-2">
        <div className="space-y-1">
          <TopicBadge topic={event.topic} />
          <p className="text-xs text-zinc-500 dark:text-zinc-400">
            from <strong className="text-zinc-700 dark:text-zinc-300">{event.from}</strong> &middot; {time}
          </p>
          <p className="font-mono text-xs text-zinc-400">{event.id}</p>
        </div>
        <button
          onClick={onClose}
          className="rounded p-1 text-zinc-400 hover:bg-zinc-200 hover:text-zinc-600 dark:hover:bg-zinc-700 dark:hover:text-zinc-300"
        >
          <X size={14} />
        </button>
      </div>
      <pre className="max-h-48 overflow-auto rounded border border-zinc-200 bg-white p-3 text-xs leading-relaxed text-zinc-700 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-300">
        {payloadStr}
      </pre>
    </div>
  );
}

export function EventStreamView() {
  const [events, setEvents] = useState<PlatformEvent[]>([]);
  const [online, setOnline] = useState<boolean | null>(null);
  const [live, setLive] = useState(true);
  const [topicFilter, setTopicFilter] = useState("");
  const [agentFilter, setAgentFilter] = useState("");
  const [selectedEvent, setSelectedEvent] = useState<PlatformEvent | null>(null);
  const [loading, setLoading] = useState(true);
  const sseRef = useRef<EventSource | null>(null);

  // ─── Health Check ──────────────────────────────────────────────────────────

  useEffect(() => {
    fetch("/api/events/health")
      .then((r) => r.json())
      .then((d: { status?: string }) => setOnline(d.status === "running"))
      .catch(() => setOnline(false));
  }, []);

  // ─── Initial Load ──────────────────────────────────────────────────────────

  const loadEvents = useCallback(async () => {
    setLoading(true);
    const params = new URLSearchParams({ limit: "200" });
    if (topicFilter) params.set("topic", topicFilter);
    if (agentFilter) params.set("from", agentFilter);
    try {
      const res = await fetch(`/api/events?${params}`);
      if (res.ok) {
        const data = (await res.json()) as PlatformEvent[];
        setEvents(data.sort((a, b) => b.ts - a.ts));
      }
    } catch {
      // ignore
    } finally {
      setLoading(false);
    }
  }, [topicFilter, agentFilter]);

  useEffect(() => {
    void loadEvents();
  }, [loadEvents]);

  // ─── SSE Live Stream ───────────────────────────────────────────────────────

  useEffect(() => {
    if (!live) {
      sseRef.current?.close();
      sseRef.current = null;
      return;
    }

    const es = new EventSource("/api/events/stream");
    sseRef.current = es;

    es.onmessage = (e) => {
      try {
        const event = JSON.parse(e.data as string) as PlatformEvent;
        // Apply filters
        if (topicFilter && !event.topic.includes(topicFilter)) return;
        if (agentFilter && event.from !== agentFilter) return;
        setEvents((prev) => [event, ...prev].slice(0, 500));
      } catch {
        // ignore malformed events
      }
    };

    es.onerror = () => {
      // SSE auto-reconnects; just note offline state briefly
    };

    return () => {
      es.close();
      sseRef.current = null;
    };
  }, [live, topicFilter, agentFilter]);

  // ─── Derived Values ────────────────────────────────────────────────────────

  const allAgents = Array.from(new Set(events.map((e) => e.from))).sort();
  const allTopicPrefixes = Array.from(
    new Set(events.map((e) => e.topic.split(".")[0]))
  ).sort();

  function handleSelectEvent(event: PlatformEvent) {
    setSelectedEvent((prev) => (prev?.id === event.id ? null : event));
  }

  // ─── Render ────────────────────────────────────────────────────────────────

  return (
    <div className="flex h-full flex-col overflow-hidden">
      {/* Header */}
      <div className="flex items-center gap-3 border-b border-zinc-200 px-4 py-3 dark:border-zinc-700">
        <Radio size={20} className="text-zinc-500 dark:text-zinc-400" />
        <h1 className="text-lg font-semibold text-zinc-900 dark:text-zinc-100">Event Stream</h1>
        <div className="ml-auto flex items-center gap-2">
          {/* Online indicator */}
          <span
            className={`flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium ${
              online === null
                ? "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"
                : online
                ? "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400"
                : "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400"
            }`}
          >
            <Activity size={10} />
            {online === null ? "checking" : online ? "online" : "offline"}
          </span>

          {/* Live toggle */}
          <button
            onClick={() => setLive((v) => !v)}
            className={`flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium transition-colors ${
              live
                ? "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400"
                : "bg-zinc-100 text-zinc-500 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-400 dark:hover:bg-zinc-700"
            }`}
          >
            <span
              className={`h-1.5 w-1.5 rounded-full ${live ? "animate-pulse bg-blue-500" : "bg-zinc-400"}`}
            />
            {live ? "Live" : "Paused"}
          </button>

          {/* Refresh */}
          <button
            onClick={() => void loadEvents()}
            className="rounded p-1.5 text-zinc-400 hover:bg-zinc-100 hover:text-zinc-600 dark:hover:bg-zinc-800 dark:hover:text-zinc-300"
            title="Refresh"
          >
            <RefreshCw size={14} />
          </button>
        </div>
      </div>

      {/* Filters */}
      <div className="flex gap-2 border-b border-zinc-200 px-4 py-2 dark:border-zinc-700">
        <Filter size={14} className="mt-1.5 shrink-0 text-zinc-400" />
        <div className="flex flex-1 flex-wrap gap-2">
          <select
            value={topicFilter}
            onChange={(e) => setTopicFilter(e.target.value)}
            className="rounded border border-zinc-200 bg-white px-2 py-1 text-xs text-zinc-700 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300"
          >
            <option value="">All topics</option>
            {allTopicPrefixes.map((p) => (
              <option key={p} value={p}>
                {p}.*
              </option>
            ))}
          </select>
          <select
            value={agentFilter}
            onChange={(e) => setAgentFilter(e.target.value)}
            className="rounded border border-zinc-200 bg-white px-2 py-1 text-xs text-zinc-700 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300"
          >
            <option value="">All agents</option>
            {allAgents.map((a) => (
              <option key={a} value={a}>
                {a}
              </option>
            ))}
          </select>
          {(topicFilter || agentFilter) && (
            <button
              onClick={() => {
                setTopicFilter("");
                setAgentFilter("");
              }}
              className="flex items-center gap-1 rounded px-2 py-1 text-xs text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300"
            >
              <X size={12} /> Clear filters
            </button>
          )}
        </div>
        <span className="self-center text-xs text-zinc-400">{events.length} events</span>
      </div>

      {/* Event list + detail */}
      <div className="flex-1 overflow-y-auto">
        {loading ? (
          <div className="flex h-32 items-center justify-center text-sm text-zinc-400">
            Loading events…
          </div>
        ) : events.length === 0 ? (
          <div className="flex h-32 flex-col items-center justify-center gap-2 text-sm text-zinc-400">
            <Radio size={24} className="opacity-40" />
            <p>No events yet — waiting for platform activity</p>
            {online === false && (
              <p className="text-xs text-red-500">Event bus is offline</p>
            )}
          </div>
        ) : (
          <div className="divide-y divide-zinc-100 dark:divide-zinc-800">
            {events.map((event) => (
              <div key={event.id}>
                <EventRow
                  event={event}
                  selected={selectedEvent?.id === event.id}
                  onSelect={handleSelectEvent}
                />
                {selectedEvent?.id === event.id && (
                  <EventDetail event={event} onClose={() => setSelectedEvent(null)} />
                )}
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}
