import { redirect, useFetcher, useLoaderData, useRevalidator, Link } from "react-router";
import { useCallback, useEffect, useMemo, useState } from "react";
import { ArrowLeft, ListOrdered } from "lucide-react";
import { auth } from "~/lib/auth.server";
import { findSeasonWithTeamsAndLeague } from "~/models/season";
import { getDraftParticipants } from "~/models/season-participant";
import { getTeamQueue } from "~/models/draft-queue";
import { QueueSection } from "~/components/draft/QueueSection";
import { Button } from "~/components/ui/button";
import { Badge } from "~/components/ui/badge";
import type { Route } from "./+types/$leagueId.draft-queue.$seasonId";

export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
  return [{ title: `Pre-Draft Queue — ${data?.season?.league?.name ?? "League"} - Brackt` }];
}

export async function loader(args: Route.LoaderArgs) {
  const { params } = args;
  const { seasonId, leagueId } = params;
  const session = await auth.api.getSession({ headers: args.request.headers });
  const userId = session?.user.id ?? null;

  if (!seasonId) {
    throw new Response("Season ID is required", { status: 400 });
  }

  const season = await findSeasonWithTeamsAndLeague(seasonId);

  if (!season) {
    throw new Response("Season not found", { status: 404 });
  }

  // Redirect if draft has started — send them to the appropriate page
  if (season.status === "draft") {
    return redirect(`/leagues/${leagueId}/draft/${seasonId}`);
  }
  if (season.status === "active" || season.status === "completed") {
    return redirect(`/leagues/${leagueId}/draft-board/${seasonId}`);
  }

  if (!userId) {
    throw new Response("You must be logged in to build a queue", { status: 401 });
  }

  const userTeam = season.teams.find((t) => t.ownerId === userId);
  if (!userTeam) {
    throw new Response("You do not have a team in this season", { status: 403 });
  }

  const [availableParticipants, userQueue] = await Promise.all([
    getDraftParticipants(seasonId),
    getTeamQueue(userTeam.id),
  ]);

  return {
    season,
    leagueId,
    userTeam,
    availableParticipants,
    userQueue,
  };
}

type QueueItem = { id: string; participantId: string };

export default function PreDraftQueue() {
  const { season, leagueId, userTeam, availableParticipants, userQueue } =
    useLoaderData<typeof loader>();
  const { revalidate } = useRevalidator();

  const [localQueue, setLocalQueue] = useState<QueueItem[]>(userQueue);

  // Sync local state when server data refreshes
  useEffect(() => {
    setLocalQueue(userQueue);
  }, [userQueue]);

  const addFetcher = useFetcher<{ success: boolean }>();
  const removeFetcher = useFetcher();
  const reorderFetcher = useFetcher();

  // After add completes, revalidate to replace the optimistic temp ID with the real one
  useEffect(() => {
    if (addFetcher.state === "idle" && addFetcher.data?.success) {
      revalidate();
    }
  }, [addFetcher.state, addFetcher.data, revalidate]);

  const queuedParticipantIds = useMemo(
    () => new Set(localQueue.map((q) => q.participantId)),
    [localQueue]
  );

  const handleAdd = useCallback(
    (participantId: string) => {
      if (queuedParticipantIds.has(participantId)) return;
      // Optimistic update with a temporary ID
      const tempId = `temp-${Date.now()}-${participantId}`;
      setLocalQueue((prev) => [...prev, { id: tempId, participantId }]);
      const formData = new FormData();
      formData.append("seasonId", season.id);
      formData.append("teamId", userTeam.id);
      formData.append("participantId", participantId);
      addFetcher.submit(formData, { method: "POST", action: "/api/queue/add" });
    },
    [queuedParticipantIds, season.id, userTeam.id, addFetcher]
  );

  const handleRemove = useCallback(
    (queueId: string) => {
      setLocalQueue((prev) => prev.filter((item) => item.id !== queueId));
      const formData = new FormData();
      formData.append("queueId", queueId);
      formData.append("teamId", userTeam.id);
      removeFetcher.submit(formData, { method: "POST", action: "/api/queue/remove" });
    },
    [userTeam.id, removeFetcher]
  );

  const handleReorder = useCallback(
    (participantIds: string[]) => {
      setLocalQueue((prev) => {
        const byParticipantId = new Map(prev.map((item) => [item.participantId, item]));
        return participantIds
          .map((pid) => byParticipantId.get(pid))
          .filter((item): item is (typeof prev)[number] => item !== undefined);
      });
      const formData = new FormData();
      formData.append("teamId", userTeam.id);
      formData.append("seasonId", season.id);
      formData.append("participantIds", JSON.stringify(participantIds));
      reorderFetcher.submit(formData, { method: "POST", action: "/api/queue/reorder" });
    },
    [userTeam.id, season.id, reorderFetcher]
  );

  return (
    <div className="container mx-auto py-8 px-4">
      {/* Header */}
      <div className="mb-6">
        <Link
          to={`/leagues/${leagueId}`}
          className="inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground mb-3"
        >
          <ArrowLeft className="h-4 w-4" />
          Back to {season.league.name}
        </Link>
        <div className="flex items-center gap-2 mb-1">
          <ListOrdered className="h-6 w-6" />
          <h1 className="text-2xl font-bold">Pre-Draft Queue</h1>
        </div>
        <p className="text-sm text-muted-foreground">
          Rank the participants you want. Your queue will carry into the live draft and determine
          your autopick order.
        </p>
      </div>

      {/* Two-panel layout */}
      <div className="grid gap-6 lg:grid-cols-3">
        {/* Participant list */}
        <div className="lg:col-span-2">
          <div className="flex items-center justify-between mb-3">
            <h2 className="font-semibold">All Participants</h2>
            <span className="text-xs text-muted-foreground">Sorted by VORP</span>
          </div>
          <div className="space-y-1">
            {availableParticipants.map((p) => {
              const inQueue = queuedParticipantIds.has(p.id);
              return (
                <div
                  key={p.id}
                  className="flex items-center gap-3 rounded-lg bg-muted/50 px-3 py-2"
                >
                  <div className="min-w-0 flex-1">
                    <p className="font-medium text-sm truncate">{p.name}</p>
                    <p className="text-xs text-muted-foreground">{p.sport.name}</p>
                  </div>
                  {p.vorpValue != null && (
                    <span className="text-xs text-muted-foreground tabular-nums shrink-0">
                      {Number(p.vorpValue).toFixed(1)}
                    </span>
                  )}
                  <Button
                    size="sm"
                    variant={inQueue ? "secondary" : "outline"}
                    disabled={inQueue}
                    onClick={() => handleAdd(p.id)}
                    className="h-7 text-xs shrink-0"
                  >
                    {inQueue ? "Queued" : "+ Add"}
                  </Button>
                </div>
              );
            })}
            {availableParticipants.length === 0 && (
              <p className="text-sm text-muted-foreground text-center py-12">
                No participants have been added to this season yet.
              </p>
            )}
          </div>
        </div>

        {/* Queue panel */}
        <div>
          <div className="flex items-center justify-between mb-3">
            <h2 className="font-semibold">Your Queue</h2>
            <Badge variant="secondary">{localQueue.length}</Badge>
          </div>
          <div className="rounded-lg border bg-card">
            <QueueSection
              queue={localQueue}
              availableParticipants={availableParticipants}
              canPick={false}
              onRemoveFromQueue={handleRemove}
              onReorder={handleReorder}
            />
          </div>
          {localQueue.length > 0 && (
            <p className="text-xs text-muted-foreground mt-2 text-center">
              Drag to reorder · Autopick follows this order
            </p>
          )}
        </div>
      </div>
    </div>
  );
}
