import { useCallback, useEffect, useMemo, useState } from "react";
import { Activity, DatabaseZap, Loader2, Wifi, WifiOff } from "lucide-react";
import type { WidgetProps } from "@mosaic/shared";

interface OrchestratorEvent {
  type: string;
  timestamp: string;
  agentId?: string;
  taskId?: string;
  data?: Record<string, unknown>;
}

interface RecentEventsResponse {
  events: OrchestratorEvent[];
}

function isMatrixSignal(event: OrchestratorEvent): boolean {
  const text = JSON.stringify(event).toLowerCase();
  return (
    text.includes("matrix") ||
    text.includes("room") ||
    text.includes("channel") ||
    text.includes("thread")
  );
}

export function OrchestratorEventsWidget({
  id: _id,
  config: _config,
}: WidgetProps): React.JSX.Element {
  const [events, setEvents] = useState<OrchestratorEvent[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [streamConnected, setStreamConnected] = useState(false);
  const [backendReady, setBackendReady] = useState<boolean | null>(null);

  const loadRecentEvents = useCallback(async (): Promise<void> => {
    try {
      const response = await fetch("/api/orchestrator/events/recent?limit=25");
      if (!response.ok) {
        throw new Error(`Unable to load events: HTTP ${String(response.status)}`);
      }
      const payload = (await response.json()) as unknown;
      const events =
        payload &&
        typeof payload === "object" &&
        "events" in payload &&
        Array.isArray(payload.events)
          ? (payload.events as RecentEventsResponse["events"])
          : [];
      setEvents(events);
      setError(null);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Unable to load events.");
    } finally {
      setIsLoading(false);
    }
  }, []);

  const loadHealth = useCallback(async (): Promise<void> => {
    try {
      const response = await fetch("/api/orchestrator/health");
      setBackendReady(response.ok);
    } catch {
      setBackendReady(false);
    }
  }, []);

  useEffect(() => {
    void loadRecentEvents();
    void loadHealth();

    const eventSource =
      typeof EventSource !== "undefined" ? new EventSource("/api/orchestrator/events") : null;
    if (eventSource) {
      eventSource.onopen = (): void => {
        setStreamConnected(true);
      };
      eventSource.onmessage = (): void => {
        void loadRecentEvents();
        void loadHealth();
      };
      eventSource.onerror = (): void => {
        setStreamConnected(false);
      };
    }

    const interval = setInterval(() => {
      void loadRecentEvents();
      void loadHealth();
    }, 15000);

    return (): void => {
      clearInterval(interval);
      eventSource?.close();
    };
  }, [loadHealth, loadRecentEvents]);

  const matrixSignals = useMemo(
    () => events.filter((event) => isMatrixSignal(event)).length,
    [events]
  );

  if (isLoading) {
    return (
      <div className="flex items-center justify-center h-full">
        <Loader2 className="w-5 h-5 text-gray-400 animate-spin" />
        <span className="ml-2 text-gray-500 text-sm">Loading orchestrator events...</span>
      </div>
    );
  }

  if (error) {
    return (
      <div className="flex flex-col items-center justify-center h-full text-center">
        <WifiOff className="w-5 h-5 text-amber-500 mb-2" />
        <span className="text-sm text-amber-600">{error}</span>
      </div>
    );
  }

  return (
    <div className="flex flex-col h-full space-y-3">
      <div className="flex items-center justify-between text-xs">
        <div className="flex items-center gap-2 text-gray-600 dark:text-gray-300">
          {streamConnected ? (
            <Wifi className="w-3 h-3 text-green-500" />
          ) : (
            <WifiOff className="w-3 h-3 text-gray-400" />
          )}
          <span>{streamConnected ? "Live stream connected" : "Polling mode"}</span>
          <span
            className={`rounded px-1.5 py-0.5 ${
              backendReady === true
                ? "bg-green-100 text-green-700 dark:bg-green-950 dark:text-green-300"
                : backendReady === false
                  ? "bg-amber-100 text-amber-700 dark:bg-amber-950 dark:text-amber-300"
                  : "bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-300"
            }`}
          >
            {backendReady === true ? "ready" : backendReady === false ? "degraded" : "unknown"}
          </span>
        </div>
        <div className="flex items-center gap-1 rounded bg-blue-50 dark:bg-blue-950 px-2 py-1 text-blue-700 dark:text-blue-300">
          <DatabaseZap className="w-3 h-3" />
          <span>Matrix signals: {matrixSignals}</span>
        </div>
      </div>

      <div className="flex-1 overflow-auto space-y-2">
        {events.length === 0 ? (
          <div className="text-center text-sm text-gray-500 py-4">
            No recent orchestration events.
          </div>
        ) : (
          events
            .slice()
            .reverse()
            .map((event, index) => (
              <div
                key={`${event.timestamp}-${event.type}-${String(index)}`}
                className="rounded border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900 px-2 py-2"
              >
                <div className="flex items-center justify-between gap-2">
                  <div className="flex items-center gap-2 min-w-0">
                    <Activity className="w-3 h-3 text-blue-500 shrink-0" />
                    <span className="text-xs font-medium text-gray-900 dark:text-gray-100 truncate">
                      {event.type}
                    </span>
                    {isMatrixSignal(event) && (
                      <span className="text-[10px] rounded bg-indigo-100 dark:bg-indigo-950 text-indigo-700 dark:text-indigo-300 px-1.5 py-0.5">
                        matrix
                      </span>
                    )}
                  </div>
                  <span className="text-[10px] text-gray-500">
                    {new Date(event.timestamp).toLocaleTimeString()}
                  </span>
                </div>
                <div className="mt-1 text-[11px] text-gray-600 dark:text-gray-300">
                  {event.taskId ? `Task ${event.taskId}` : "Task n/a"}
                  {event.agentId ? ` · Agent ${event.agentId.slice(0, 8)}` : ""}
                </div>
              </div>
            ))
        )}
      </div>
    </div>
  );
}
