"use client";

import { useEffect, useRef, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import type { AgentMessageRole, AgentSessionStatus } from "@mosaic/shared";
import { apiGet } from "@/lib/api/client";

const MISSION_CONTROL_SESSIONS_QUERY_KEY = ["mission-control", "sessions"] as const;
const SESSIONS_REFRESH_INTERVAL_MS = 15_000;

export type MissionControlMessageRole = AgentMessageRole;

export interface MissionControlSession {
  id: string;
  providerId: string;
  providerType: string;
  label?: string;
  status: AgentSessionStatus;
  parentSessionId?: string;
  createdAt: string;
  updatedAt: string;
  metadata?: Record<string, unknown>;
}

interface MissionControlSessionsResponse {
  sessions: MissionControlSession[];
}

export interface MissionControlStreamMessage {
  id: string;
  sessionId: string;
  role: MissionControlMessageRole;
  content: string;
  timestamp: string;
  metadata?: Record<string, unknown>;
}

export type MissionControlConnectionStatus = "connecting" | "connected" | "error";

export interface UseSessionsResult {
  sessions: MissionControlSession[];
  loading: boolean;
  error: Error | null;
}

export interface UseSessionStreamResult {
  messages: MissionControlStreamMessage[];
  status: MissionControlConnectionStatus;
  error: string | null;
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null;
}

function isMessageRole(value: unknown): value is MissionControlMessageRole {
  return value === "assistant" || value === "system" || value === "tool" || value === "user";
}

function isMissionControlStreamMessage(value: unknown): value is MissionControlStreamMessage {
  if (!isRecord(value)) {
    return false;
  }

  const { id, sessionId, role, content, timestamp, metadata } = value;

  if (
    typeof id !== "string" ||
    typeof sessionId !== "string" ||
    !isMessageRole(role) ||
    typeof content !== "string" ||
    typeof timestamp !== "string"
  ) {
    return false;
  }

  if (metadata !== undefined && !isRecord(metadata)) {
    return false;
  }

  return true;
}

/**
 * Fetches Mission Control sessions.
 */
export function useSessions(): UseSessionsResult {
  const query = useQuery<MissionControlSessionsResponse>({
    queryKey: MISSION_CONTROL_SESSIONS_QUERY_KEY,
    queryFn: async (): Promise<MissionControlSessionsResponse> => {
      return apiGet<MissionControlSessionsResponse>("/api/mission-control/sessions");
    },
    refetchInterval: SESSIONS_REFRESH_INTERVAL_MS,
  });

  return {
    sessions: query.data?.sessions ?? [],
    loading: query.isLoading,
    error: query.error ?? null,
  };
}

/**
 * Backward-compatible alias for early Mission Control integration.
 */
export function useMissionControl(): UseSessionsResult {
  return useSessions();
}

/**
 * Streams Mission Control session messages over SSE.
 */
export function useSessionStream(sessionId: string): UseSessionStreamResult {
  const [messages, setMessages] = useState<MissionControlStreamMessage[]>([]);
  const [status, setStatus] = useState<MissionControlConnectionStatus>("connecting");
  const [error, setError] = useState<string | null>(null);

  const eventSourceRef = useRef<EventSource | null>(null);

  useEffect(() => {
    if (eventSourceRef.current !== null) {
      eventSourceRef.current.close();
      eventSourceRef.current = null;
    }

    setMessages([]);
    setError(null);

    if (!sessionId) {
      setStatus("connecting");
      return;
    }

    if (typeof EventSource === "undefined") {
      setStatus("error");
      setError("Mission Control stream is not supported by this browser.");
      return;
    }

    setStatus("connecting");

    const source = new EventSource(
      `/api/mission-control/sessions/${encodeURIComponent(sessionId)}/stream`
    );
    eventSourceRef.current = source;

    source.onopen = (): void => {
      setStatus("connected");
      setError(null);
    };

    source.onmessage = (event: MessageEvent<string>): void => {
      try {
        const parsed = JSON.parse(event.data) as unknown;
        if (!isMissionControlStreamMessage(parsed)) {
          return;
        }

        setMessages((previousMessages) => [...previousMessages, parsed]);
      } catch {
        // Ignore malformed events from the stream.
      }
    };

    source.onerror = (): void => {
      if (source.readyState === EventSource.CONNECTING) {
        setStatus("connecting");
        setError(null);
        return;
      }

      setStatus("error");
      setError("Mission Control stream disconnected.");
    };

    return (): void => {
      source.close();
      if (eventSourceRef.current === source) {
        eventSourceRef.current = null;
      }
    };
  }, [sessionId]);

  return {
    messages,
    status,
    error,
  };
}
