"use client";

import { useMemo, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { AgentSession } from "@mosaic/shared";
import { ChevronRight, Loader2, X } from "lucide-react";
import { KillAllDialog } from "@/components/mission-control/KillAllDialog";
import { Badge } from "@/components/ui/badge";
import type { BadgeVariant } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Collapsible } from "@/components/ui/collapsible";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Skeleton } from "@/components/ui/skeleton";
import { apiGet, apiPost } from "@/lib/api/client";

const SESSIONS_QUERY_KEY = ["mission-control", "sessions"] as const;
const SESSIONS_POLL_INTERVAL_MS = 5_000;

type MissionControlSessionStatus = AgentSession["status"] | "killed";

interface MissionControlSession extends Omit<AgentSession, "status" | "createdAt" | "updatedAt"> {
  status: MissionControlSessionStatus;
  createdAt: string | Date;
  updatedAt: string | Date;
}

interface SessionsPayload {
  sessions: MissionControlSession[];
}

interface ProviderSessionGroup {
  providerId: string;
  providerType: string;
  sessions: MissionControlSession[];
}

export interface GlobalAgentRosterProps {
  onSelectSession?: (sessionId: string) => void;
  selectedSessionId?: string | undefined;
}

function getStatusVariant(status: MissionControlSessionStatus): BadgeVariant {
  switch (status) {
    case "active":
      return "status-success";
    case "paused":
      return "status-warning";
    case "killed":
      return "status-error";
    default:
      return "status-neutral";
  }
}

function truncateSessionId(sessionId: string): string {
  return sessionId.slice(0, 8);
}

function resolveProviderName(providerId: string, providerType: string): string {
  return providerId === providerType ? providerId : `${providerId} (${providerType})`;
}

function groupByProvider(sessions: MissionControlSession[]): ProviderSessionGroup[] {
  const grouped = new Map<string, ProviderSessionGroup>();

  for (const session of sessions) {
    const existing = grouped.get(session.providerId);
    if (existing) {
      existing.sessions.push(session);
      continue;
    }

    grouped.set(session.providerId, {
      providerId: session.providerId,
      providerType: session.providerType,
      sessions: [session],
    });
  }

  return Array.from(grouped.values()).sort((a, b) => a.providerId.localeCompare(b.providerId));
}

async function fetchSessions(): Promise<MissionControlSession[]> {
  const payload = await apiGet<MissionControlSession[] | SessionsPayload>(
    "/api/mission-control/sessions"
  );
  return Array.isArray(payload) ? payload : payload.sessions;
}

function toKillAllSessions(sessions: MissionControlSession[]): AgentSession[] {
  return sessions
    .filter(
      (session): session is MissionControlSession & { status: AgentSession["status"] } =>
        session.status !== "killed"
    )
    .map((session) => ({
      ...session,
      createdAt:
        session.createdAt instanceof Date ? session.createdAt : new Date(session.createdAt),
      updatedAt:
        session.updatedAt instanceof Date ? session.updatedAt : new Date(session.updatedAt),
    }));
}

export function GlobalAgentRoster({
  onSelectSession,
  selectedSessionId,
}: GlobalAgentRosterProps): React.JSX.Element {
  const queryClient = useQueryClient();
  const [openProviders, setOpenProviders] = useState<Record<string, boolean>>({});

  const sessionsQuery = useQuery<MissionControlSession[]>({
    queryKey: SESSIONS_QUERY_KEY,
    queryFn: fetchSessions,
    refetchInterval: SESSIONS_POLL_INTERVAL_MS,
  });

  const killMutation = useMutation({
    mutationFn: async (sessionId: string): Promise<string> => {
      await apiPost<{ message: string }>(`/api/mission-control/sessions/${sessionId}/kill`, {
        force: false,
      });
      return sessionId;
    },
    onSuccess: (): void => {
      void queryClient.invalidateQueries({ queryKey: SESSIONS_QUERY_KEY });
    },
  });

  const groupedSessions = useMemo(
    () => groupByProvider(sessionsQuery.data ?? []),
    [sessionsQuery.data]
  );

  const killAllSessions = useMemo(
    () => toKillAllSessions(sessionsQuery.data ?? []),
    [sessionsQuery.data]
  );

  const totalSessionCount = sessionsQuery.data?.length ?? 0;

  const pendingKillSessionId = killMutation.isPending ? killMutation.variables : undefined;

  const toggleProvider = (providerId: string): void => {
    setOpenProviders((prev) => ({
      ...prev,
      [providerId]: !(prev[providerId] ?? true),
    }));
  };

  const isProviderOpen = (providerId: string): boolean => openProviders[providerId] ?? true;

  const handleKillAllComplete = (): void => {
    void queryClient.invalidateQueries({ queryKey: SESSIONS_QUERY_KEY });
  };

  return (
    <Card className="flex h-full min-h-0 flex-col">
      <CardHeader className="pb-2">
        <CardTitle className="flex items-center justify-between gap-2 text-base">
          <span>Agent Roster</span>
          <div className="flex items-center gap-2">
            {totalSessionCount > 0 ? (
              <KillAllDialog sessions={killAllSessions} onComplete={handleKillAllComplete} />
            ) : null}
            {sessionsQuery.isFetching && !sessionsQuery.isLoading ? (
              <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" aria-hidden="true" />
            ) : null}
          </div>
        </CardTitle>
      </CardHeader>
      <CardContent className="min-h-0 flex-1 px-3 pb-3">
        {sessionsQuery.isLoading ? (
          <ScrollArea className="h-full">
            <div className="space-y-2 pr-1">
              {Array.from({ length: 6 }).map((_, index) => (
                <Skeleton key={`roster-skeleton-${String(index)}`} className="h-10 w-full" />
              ))}
            </div>
          </ScrollArea>
        ) : sessionsQuery.error ? (
          <div className="flex h-full items-center justify-center text-center text-sm text-red-500">
            Failed to load agents: {sessionsQuery.error.message}
          </div>
        ) : groupedSessions.length === 0 ? (
          <div className="flex h-full items-center justify-center text-sm text-muted-foreground">
            No active agents
          </div>
        ) : (
          <ScrollArea className="h-full">
            <div className="space-y-3 pr-1">
              {groupedSessions.map((group) => {
                const providerOpen = isProviderOpen(group.providerId);

                return (
                  <Collapsible key={group.providerId} open={providerOpen} className="space-y-1">
                    <button
                      type="button"
                      onClick={() => {
                        toggleProvider(group.providerId);
                      }}
                      className="flex w-full items-center gap-2 rounded-md px-1 py-1 text-left text-sm hover:bg-muted/40"
                      aria-expanded={providerOpen}
                    >
                      <ChevronRight
                        className={`h-4 w-4 text-muted-foreground transition-transform ${providerOpen ? "rotate-90" : ""}`}
                        aria-hidden="true"
                      />
                      <span className="font-medium">
                        {resolveProviderName(group.providerId, group.providerType)}
                      </span>
                      <span className="ml-auto text-xs text-muted-foreground">
                        {group.sessions.length}
                      </span>
                    </button>
                    {providerOpen ? (
                      <div className="space-y-1 pl-2">
                        {group.sessions.map((session) => {
                          const isSelected = selectedSessionId === session.id;
                          const isKilling = pendingKillSessionId === session.id;

                          return (
                            <div
                              key={session.id}
                              role="button"
                              tabIndex={0}
                              onClick={() => {
                                onSelectSession?.(session.id);
                              }}
                              onKeyDown={(event) => {
                                if (event.key === "Enter" || event.key === " ") {
                                  event.preventDefault();
                                  onSelectSession?.(session.id);
                                }
                              }}
                              className="flex items-center justify-between gap-2 rounded-md border border-transparent px-2 py-1.5 transition-colors hover:bg-muted/40"
                              style={
                                isSelected
                                  ? {
                                      borderColor: "rgba(47, 128, 255, 0.35)",
                                      backgroundColor: "rgba(47, 128, 255, 0.08)",
                                    }
                                  : undefined
                              }
                            >
                              <div className="flex min-w-0 items-center gap-2">
                                <span className="font-mono text-xs" title={session.id}>
                                  {truncateSessionId(session.id)}
                                </span>
                                <Badge
                                  variant={getStatusVariant(session.status)}
                                  className="capitalize"
                                >
                                  {session.status}
                                </Badge>
                              </div>
                              <Button
                                variant="ghost"
                                size="sm"
                                className="h-7 min-h-7 w-7 min-w-7 p-0"
                                disabled={isKilling}
                                onClick={(event) => {
                                  event.stopPropagation();
                                  killMutation.mutate(session.id);
                                }}
                                aria-label={`Kill session ${truncateSessionId(session.id)}`}
                              >
                                {isKilling ? (
                                  <Loader2
                                    className="h-3.5 w-3.5 animate-spin"
                                    aria-hidden="true"
                                  />
                                ) : (
                                  <X className="h-3.5 w-3.5" aria-hidden="true" />
                                )}
                              </Button>
                            </div>
                          );
                        })}
                      </div>
                    ) : null}
                  </Collapsible>
                );
              })}
            </div>
          </ScrollArea>
        )}
      </CardContent>
    </Card>
  );
}
