import { memo, useCallback, useMemo, useRef, useState } from "react";
import { useVirtualizer } from "@tanstack/react-virtual";
import { Button } from "~/components/ui/button";
import { Badge } from "~/components/ui/badge";
import { Checkbox } from "~/components/ui/checkbox";
import { MiniDraftGrid, type MiniDraftGridProps } from "~/components/draft/MiniDraftGrid";
import {
  Popover,
  PopoverTrigger,
  PopoverContent,
} from "~/components/ui/popover";
import {
  Sheet,
  SheetTrigger,
  SheetContent,
  SheetTitle,
  SheetFooter,
  SheetClose,
} from "~/components/ui/sheet";
import { ListPlus, ListX, ChevronDown, Eye, EyeOff, SlidersHorizontal } from "lucide-react";

type ListItem =
  | { type: "participant"; index: number; key: string }
  | { type: "divider"; round: number; key: string };

function getParticipantState(
  participant: { id: string; sport: { id: string } },
  draftedParticipantIds: Set<string>,
  queueMap: Map<string, string>,
  eligibility: {
    eligibleSportIds: Set<string>;
    ineligibleReasons: Record<string, string>;
  } | null,
  watchedParticipantIds: Set<string>
) {
  const isDrafted = draftedParticipantIds.has(participant.id);
  const isInQueue = queueMap.has(participant.id);
  const isEligible = eligibility
    ? eligibility.eligibleSportIds.has(participant.sport.id)
    : true;
  const ineligibleReason = eligibility?.ineligibleReasons[participant.sport.id];
  const isWatched = watchedParticipantIds.has(participant.id);
  return { isDrafted, isInQueue, isEligible, ineligibleReason, isWatched };
}

interface SportFilterContentProps {
  sportsForDropdown: Array<{ name: string; isDrafted: boolean }>;
  sportFilterSet: Set<string>;
  hideCompletedSports: boolean;
  hasTeam: boolean;
  variant: "sheet" | "popover";
  onToggleSport: (sport: string, checked: boolean | "indeterminate") => void;
  onHideCompletedSportsChange: (hide: boolean) => void;
}

function SportFilterContent({
  sportsForDropdown,
  sportFilterSet,
  hideCompletedSports,
  hasTeam,
  variant,
  onToggleSport,
  onHideCompletedSportsChange,
}: SportFilterContentProps) {
  const isSheet = variant === "sheet";
  const idPrefix = isSheet ? "sheet-sport-filter-" : "popover-sport-filter-";
  const listClass = isSheet
    ? "overflow-y-auto flex-1 px-4"
    : "max-h-64 overflow-y-auto p-2 space-y-0.5";
  const itemBaseClass = isSheet
    ? "flex items-center gap-4 py-4 border-b last:border-b-0 cursor-pointer text-base"
    : "flex items-center gap-2 px-2 py-2 rounded-sm hover:bg-accent cursor-pointer text-sm";
  const toggleLabelClass = isSheet
    ? "flex items-center gap-4 py-2 cursor-pointer text-base"
    : "flex items-center gap-2 px-4 py-3 cursor-pointer text-sm";

  return (
    <>
      <div className={listClass}>
        {sportsForDropdown
          .filter(({ isDrafted }) => !isDrafted || !hideCompletedSports)
          .map(({ name, isDrafted }) => {
            const checkboxId = `${idPrefix}${name.replace(/\s+/g, "-").toLowerCase()}`;
            return (
              <label
                key={name}
                htmlFor={checkboxId}
                className={`${itemBaseClass}${isDrafted ? " text-muted-foreground" : ""}`}
              >
                <Checkbox
                  id={checkboxId}
                  checked={sportFilterSet.has(name)}
                  onCheckedChange={(checked) => onToggleSport(name, checked)}
                />
                {name}
              </label>
            );
          })}
      </div>
      {hasTeam && (
        isSheet ? (
          <div className="px-4 border-t pt-3">
            <label className={toggleLabelClass}>
              <Checkbox
                checked={!hideCompletedSports}
                onCheckedChange={(checked) =>
                  onHideCompletedSportsChange(checked === false)
                }
              />
              <span>Show drafted sports</span>
            </label>
          </div>
        ) : (
          <>
            <hr className="mx-2 border-border" />
            <label className={toggleLabelClass}>
              <Checkbox
                checked={!hideCompletedSports}
                onCheckedChange={(checked) =>
                  onHideCompletedSportsChange(checked === false)
                }
              />
              <span>Show drafted sports</span>
            </label>
          </>
        )
      )}
    </>
  );
}

interface AvailableParticipantsSectionProps {
  participants: Array<{
    id: string;
    name: string;
    sport: {
      id: string;
      name: string;
    };
  }>;
  participantRanks: Map<string, { overallRank: number; sportRank: number }>;
  miniDraftGrid?: MiniDraftGridProps;
  searchQuery: string;
  sportFilters: string[];
  hideDrafted: boolean;
  hideIneligible: boolean;
  hideCompletedSports: boolean;
  userDraftedSportNames: Set<string>;
  uniqueSports: string[];
  draftedParticipantIds: Set<string>;
  queue: Array<{ id: string; participantId: string }>;
  eligibility: {
    eligibleSportIds: Set<string>;
    ineligibleReasons: Record<string, string>;
  } | null;
  canPick: boolean;
  hasTeam: boolean;
  onSearchChange: (query: string) => void;
  onSportFiltersChange: (sports: string[]) => void;
  onHideDraftedChange: (hide: boolean) => void;
  onHideIneligibleChange: (hide: boolean) => void;
  onHideCompletedSportsChange: (hide: boolean) => void;
  onMakePick: (participantId: string) => void;
  onAddToQueue: (participantId: string) => void;
  onRemoveFromQueue: (queueId: string) => void;
  projectedPicks?: Array<{ round: number; picksFromNow: number }>;
  watchedParticipantIds: Set<string>;
  onToggleWatchlist: (participantId: string) => void;
  showOnlyWatched: boolean;
  onShowOnlyWatchedChange: (show: boolean) => void;
}

export const AvailableParticipantsSection = memo(function AvailableParticipantsSection({
  participants,
  participantRanks,
  miniDraftGrid,
  searchQuery,
  sportFilters,
  hideDrafted,
  hideIneligible,
  hideCompletedSports,
  userDraftedSportNames,
  uniqueSports,
  draftedParticipantIds,
  queue,
  eligibility,
  canPick,
  hasTeam,
  onSearchChange,
  onSportFiltersChange,
  onHideDraftedChange,
  onHideIneligibleChange,
  onHideCompletedSportsChange,
  onMakePick,
  onAddToQueue,
  onRemoveFromQueue,
  projectedPicks,
  watchedParticipantIds,
  onToggleWatchlist,
  showOnlyWatched,
  onShowOnlyWatchedChange,
}: AvailableParticipantsSectionProps) {
  const queueMap = useMemo(
    () => new Map(queue.map((item) => [item.participantId, item.id])),
    [queue]
  );

  const sportFilterSet = useMemo(() => new Set(sportFilters), [sportFilters]);

  const sportsForDropdown = useMemo(() => {
    return uniqueSports.map((s) => ({
      name: s,
      isDrafted: hasTeam && userDraftedSportNames.has(s),
    }));
  }, [uniqueSports, userDraftedSportNames, hasTeam]);

  const triggerText = useMemo(
    () =>
      sportFilters.length === 0
        ? "All Sports"
        : sportFilters.length === 1
          ? sportFilters[0]
          : `${sportFilters.length} Sports`,
    [sportFilters]
  );

  const triggerAriaLabel = useMemo(
    () =>
      sportFilters.length === 0
        ? "Filter by sport: All Sports"
        : sportFilters.length === 1
          ? `Filter by sport: ${sportFilters[0]}`
          : `Filter by sport: ${sportFilters.length} sports selected`,
    [sportFilters]
  );

  const handleToggleSport = useCallback(
    (sport: string, checked: boolean | "indeterminate") => {
      if (checked === true) {
        onSportFiltersChange([...sportFilters, sport]);
      } else {
        onSportFiltersChange(sportFilters.filter((s) => s !== sport));
      }
    },
    [sportFilters, onSportFiltersChange]
  );

  const handleReset = useCallback(() => {
    onSportFiltersChange([]);
    onHideCompletedSportsChange(false);
  }, [onSportFiltersChange, onHideCompletedSportsChange]);

  const emptyMessage = useMemo(() => {
    if (participants.length > 0) return null;
    const active: string[] = [];
    if (hideDrafted) active.push("drafted players");
    if (hideIneligible && eligibility) active.push("ineligible players");
    if (hideCompletedSports) active.push("drafted sports");
    if (sportFilters.length > 0) active.push("other sports");
    if (active.length === 0) return "No participants found.";
    return `No participants found. Try showing ${active.join(", ")}.`;
  }, [participants.length, hideDrafted, hideIneligible, hideCompletedSports, eligibility, sportFilters]);

  const hasActiveFilters = sportFilters.length > 0 || hideCompletedSports;

  const anyFilterActive = searchQuery !== "" || sportFilters.length > 0 || hideDrafted || hideIneligible || hideCompletedSports;

  const listItems = useMemo(() => {
    const items: ListItem[] = [];
    if (!projectedPicks || projectedPicks.length === 0 || anyFilterActive) {
      for (let i = 0; i < participants.length; i++) {
        items.push({ type: "participant", index: i, key: participants[i].id });
      }
      return items;
    }
    const dividersByAfterIndex = new Map<number, number>();
    for (const pp of projectedPicks) {
      if (pp.picksFromNow <= 0) continue;
      const afterIndex = pp.picksFromNow - 1;
      if (afterIndex >= 0 && afterIndex < participants.length - 1) {
        dividersByAfterIndex.set(afterIndex, pp.round);
      }
    }
    for (let i = 0; i < participants.length; i++) {
      items.push({ type: "participant", index: i, key: participants[i].id });
      const dividerRound = dividersByAfterIndex.get(i);
      if (dividerRound !== undefined) {
        items.push({ type: "divider", round: dividerRound, key: `divider-rd${dividerRound}` });
      }
    }
    return items;
  }, [participants, projectedPicks, anyFilterActive]);

  const parentRef = useRef<HTMLDivElement>(null);
  const virtualizer = useVirtualizer({
    count: listItems.length,
    getScrollElement: () => parentRef.current,
    estimateSize: (index) => listItems[index]?.type === "divider" ? 36 : 72,
    overscan: 5,
    getItemKey: (index) => listItems[index].key,
  });

  const desktopGridClass = hasTeam
    ? "grid-cols-[60px_60px_1fr_140px]"
    : "grid-cols-[60px_60px_1fr]";

  const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);

  return (
    <div className="flex flex-col h-full">
      {miniDraftGrid && (
        <div className="px-4 pt-4 pb-2 flex-shrink-0 border-b">
          <MiniDraftGrid {...miniDraftGrid} />
        </div>
      )}
      <div className="px-4 pt-4 pb-2 flex-shrink-0">
        <div className="flex flex-col gap-2 md:flex-row md:flex-wrap md:items-center">
          <div className="flex gap-2 md:contents">
            <input
              type="text"
              placeholder="Search participants..."
              value={searchQuery}
              onChange={(e) => onSearchChange(e.target.value)}
              className="flex-1 min-w-0 px-3 py-2 h-9 border rounded-md text-base md:text-sm bg-background text-foreground"
            />

            <Button
              variant="outline"
              size="sm"
              className="md:hidden shrink-0 h-9 gap-1.5"
              onClick={() => setMobileFiltersOpen((prev) => !prev)}
              aria-expanded={mobileFiltersOpen}
              aria-label="Toggle filters"
            >
              <SlidersHorizontal className="h-4 w-4" />
              Filters
            </Button>

            <div className="hidden md:block shrink-0">
              <Popover>
                <PopoverTrigger asChild>
                  <Button
                    variant="outline"
                    aria-label={triggerAriaLabel}
                    className="w-[160px] justify-between text-sm font-normal"
                  >
                    <span className="truncate">{triggerText}</span>
                    <ChevronDown className="h-4 w-4 shrink-0 opacity-50" />
                  </Button>
                </PopoverTrigger>
                <PopoverContent className="w-72 p-0" align="start">
                  {hasActiveFilters && (
                    <div className="flex justify-end px-2 pt-2">
                      <Button
                        variant="ghost"
                        size="sm"
                        className="h-auto px-2 py-1 text-xs"
                        onClick={handleReset}
                      >
                        Reset
                      </Button>
                    </div>
                  )}
                  <SportFilterContent
                    sportsForDropdown={sportsForDropdown}
                    sportFilterSet={sportFilterSet}
                    hideCompletedSports={hideCompletedSports}
                    hasTeam={hasTeam}
                    variant="popover"
                    onToggleSport={handleToggleSport}
                    onHideCompletedSportsChange={onHideCompletedSportsChange}
                  />
                </PopoverContent>
              </Popover>
            </div>
          </div>

          <div className={`flex gap-2 flex-wrap md:contents ${mobileFiltersOpen ? "" : "hidden md:contents"}`}>
            <div className="md:hidden">
              <Sheet>
                <SheetTrigger asChild>
                  <Button
                    variant="outline"
                    aria-label={triggerAriaLabel}
                    className="justify-between text-base font-normal w-full"
                  >
                    <span className="truncate">{triggerText}</span>
                    <ChevronDown className="h-4 w-4 shrink-0 opacity-50" />
                  </Button>
                </SheetTrigger>
                <SheetContent side="bottom" className="max-h-[70vh] pt-12" aria-describedby={undefined}>
                  <SheetTitle className="sr-only">Filter by sport</SheetTitle>
                  <SportFilterContent
                    sportsForDropdown={sportsForDropdown}
                    sportFilterSet={sportFilterSet}
                    hideCompletedSports={hideCompletedSports}
                    hasTeam={hasTeam}
                    variant="sheet"
                    onToggleSport={handleToggleSport}
                    onHideCompletedSportsChange={onHideCompletedSportsChange}
                  />
                  <SheetFooter className="px-4 pb-8 flex-row gap-2">
                    {hasActiveFilters && (
                      <Button
                        variant="outline"
                        className="flex-1"
                        onClick={handleReset}
                      >
                        Reset
                      </Button>
                    )}
                    <SheetClose asChild>
                      <Button className="flex-1">Done</Button>
                    </SheetClose>
                  </SheetFooter>
                </SheetContent>
              </Sheet>
            </div>

            <label className="flex flex-1 items-center gap-2 text-sm cursor-pointer px-3 py-2 border rounded-md md:shrink-0 md:flex-none">
              <Checkbox
                checked={!hideDrafted}
                onCheckedChange={(checked) => onHideDraftedChange(checked === false)}
              />
              <span>Show Drafted</span>
            </label>

            {hasTeam && eligibility && (
              <label className="flex flex-1 items-center gap-2 text-sm cursor-pointer px-3 py-2 border rounded-md md:shrink-0 md:flex-none">
                <Checkbox
                  checked={!hideIneligible}
                  onCheckedChange={(checked) => onHideIneligibleChange(checked === false)}
                />
                <span>Show Ineligible</span>
              </label>
            )}

            {hasTeam && (
              <label className="flex flex-1 items-center gap-2 text-sm cursor-pointer px-3 py-2 border rounded-md md:shrink-0 md:flex-none">
                <Checkbox
                  checked={showOnlyWatched}
                  onCheckedChange={(checked) => onShowOnlyWatchedChange(checked === true)}
                  disabled={watchedParticipantIds.size === 0}
                />
                <span>Watched Only</span>
              </label>
            )}
          </div>
        </div>
      </div>

      <div className={`hidden md:grid ${desktopGridClass} bg-muted border-b text-sm font-semibold flex-shrink-0 px-4`}>
        <span className="text-center p-3 px-0">OVR</span>
        <span className="text-center p-3 px-0">SPR</span>
        <span className="text-left p-3">Participant</span>
      </div>

      <div ref={parentRef} className="flex-1 overflow-y-auto">
        {participants.length === 0 ? (
          <div className="text-center py-8 text-muted-foreground text-sm">
            {emptyMessage}
          </div>
        ) : (
          <div
            style={{
              height: virtualizer.getTotalSize(),
              position: "relative",
              width: "100%",
            }}
          >
            {virtualizer.getVirtualItems().map((virtualItem) => {
              const listItem = listItems[virtualItem.index];

              if (listItem.type === "divider") {
                return (
                  <div
                    key={virtualItem.key}
                    data-index={virtualItem.index}
                    ref={virtualizer.measureElement}
                    style={{
                      position: "absolute",
                      top: virtualItem.start,
                      left: 0,
                      right: 0,
                    }}
                  >
                    <div className="flex items-center gap-2 px-4 py-2">
                      <div className="flex-1 border-t-2 border-dashed border-electric/40" />
                      <span className="text-sm font-semibold text-electric whitespace-nowrap">
                        Projected Round {listItem.round} Pick
                      </span>
                      <div className="flex-1 border-t-2 border-dashed border-electric/40" />
                    </div>
                  </div>
                );
              }

              const participant = participants[listItem.index];
              const { isDrafted, isInQueue, isEligible, ineligibleReason, isWatched } =
                getParticipantState(participant, draftedParticipantIds, queueMap, eligibility, watchedParticipantIds);
              const rank = participantRanks.get(participant.id);
              const followsDivider = listItems[virtualItem.index - 1]?.type === "divider";

              return (
                <div
                  key={virtualItem.key}
                  data-index={virtualItem.index}
                  ref={virtualizer.measureElement}
                  style={{
                    position: "absolute",
                    top: virtualItem.start,
                    left: 0,
                    right: 0,
                  }}
                >
                  <div className="md:hidden px-4 py-1">
                    <div
                      className={`bg-card border rounded-lg p-3 flex items-start justify-between gap-3 transition-colors ${
                        isDrafted
                          ? "bg-muted/50 opacity-60"
                          : !isEligible
                            ? "bg-destructive/10 opacity-75"
                            : isWatched
                              ? "bg-emerald-500/10 border-l-2 border-l-emerald-500/30"
                              : ""
                      }`}
                    >
                      <div className="flex flex-col gap-1 min-w-0">
                        <span
                          className={`font-semibold text-sm truncate ${!isEligible && !isDrafted ? "text-muted-foreground" : ""}`}
                        >
                          {participant.name}
                        </span>
                        <div className="flex flex-wrap gap-1 items-center">
                          <Badge variant="outline" className="text-xs">
                            {participant.sport.name}
                          </Badge>
                          <span className="text-xs text-muted-foreground tabular-nums">
                            OVR {rank?.overallRank} · SPR {rank?.sportRank}
                          </span>
                          {isDrafted && (
                            <Badge variant="secondary" className="text-xs">
                              Drafted
                            </Badge>
                          )}
                          {!isDrafted && !isEligible && (
                            <Badge
                              variant="destructive"
                              className="text-xs"
                              title={ineligibleReason}
                            >
                              Ineligible
                            </Badge>
                          )}
                          {isInQueue && !isDrafted && isEligible && (
                            <Badge variant="default" className="text-xs">
                              Queued
                            </Badge>
                          )}
                        </div>
                      </div>
                      {hasTeam && !isDrafted && (
                        <div className="flex gap-2 flex-shrink-0">
                          <Button
                            variant="ghost"
                            size="sm"
                            className="min-h-[44px] min-w-[44px]"
                            onClick={() => onToggleWatchlist(participant.id)}
                            title={isWatched ? "Remove from watchlist" : "Add to watchlist"}
                          >
                            {isWatched
                              ? <EyeOff className="h-4 w-4 text-emerald-400" />
                              : <Eye className="h-4 w-4" />}
                          </Button>
                          {!isInQueue ? (
                            <Button
                              variant="ghost"
                              size="sm"
                              className="min-h-[44px] min-w-[44px]"
                              onClick={() => onAddToQueue(participant.id)}
                              title={!isEligible ? ineligibleReason : "Add to queue"}
                              disabled={!isEligible}
                            >
                              <ListPlus className="h-4 w-4" />
                            </Button>
                          ) : (
                            <Button
                              variant="ghost"
                              size="sm"
                              className="min-h-[44px] min-w-[44px]"
                              onClick={() => {
                                const queueId = queueMap.get(participant.id);
                                if (queueId) onRemoveFromQueue(queueId);
                              }}
                              title="Remove from queue"
                            >
                              <ListX className="h-4 w-4" />
                            </Button>
                          )}
                          <Button
                            variant="default"
                            size="sm"
                            className="min-h-[44px]"
                            onClick={() => onMakePick(participant.id)}
                            disabled={!canPick || !isEligible}
                            title={
                              !canPick
                                ? "Not your turn"
                                : !isEligible
                                  ? ineligibleReason
                                  : undefined
                            }
                          >
                            Draft
                          </Button>
                        </div>
                      )}
                    </div>
                  </div>

                  <div
                    className={`hidden md:grid ${desktopGridClass} items-center px-4 transition-colors ${
                      followsDivider ? "" : "border-t"
                    } ${
                      isDrafted
                        ? "bg-muted/50 opacity-60"
                        : !isEligible
                          ? "bg-destructive/10 opacity-75"
                          : isWatched
                            ? "bg-emerald-500/10 border-l-2 border-l-emerald-500/30"
                            : "hover:bg-muted/50"
                    }`}
                    title={
                      !isEligible && !isDrafted ? ineligibleReason : undefined
                    }
                  >
                    <span className="text-center text-muted-foreground tabular-nums p-3 px-0">
                      {rank?.overallRank}
                    </span>
                    <span className="text-center text-muted-foreground tabular-nums p-3 px-0">
                      {rank?.sportRank}
                    </span>
                    <div className="p-3">
                      <div className="flex items-center gap-2">
                        <span
                          className={`font-medium ${!isEligible && !isDrafted ? "text-muted-foreground" : ""}`}
                        >
                          {participant.name}
                        </span>
                        <Badge variant="outline" className="text-xs">
                          {participant.sport.name}
                        </Badge>
                        {isDrafted && (
                          <Badge variant="secondary" className="text-xs">
                            Drafted
                          </Badge>
                        )}
                        {!isDrafted && !isEligible && (
                          <Badge
                            variant="destructive"
                            className="text-xs"
                            title={ineligibleReason}
                          >
                            Ineligible
                          </Badge>
                        )}
                        {isInQueue && !isDrafted && isEligible && (
                          <Badge variant="default" className="text-xs">
                            Queued
                          </Badge>
                        )}
                      </div>
                    </div>
                    {hasTeam && (
                      <div className="p-3">
                        <div className="flex gap-2 justify-end items-center">
                          {!isDrafted && (
                            <>
                              <Button
                                variant="ghost"
                                size="sm"
                                onClick={() => onToggleWatchlist(participant.id)}
                                title={isWatched ? "Remove from watchlist" : "Add to watchlist"}
                              >
                                {isWatched
                                  ? <EyeOff className="h-4 w-4 text-emerald-400" />
                                  : <Eye className="h-4 w-4" />}
                              </Button>
                              {!isInQueue ? (
                                <Button
                                  variant="ghost"
                                  size="sm"
                                  onClick={() => onAddToQueue(participant.id)}
                                  title={
                                    !isEligible
                                      ? ineligibleReason
                                      : "Add to queue"
                                  }
                                  disabled={!isEligible}
                                >
                                  <ListPlus className="h-4 w-4" />
                                </Button>
                              ) : (
                                <Button
                                  variant="ghost"
                                  size="sm"
                                  onClick={() => {
                                    const queueId = queueMap.get(participant.id);
                                    if (queueId) onRemoveFromQueue(queueId);
                                  }}
                                  title="Remove from queue"
                                >
                                  <ListX className="h-4 w-4" />
                                </Button>
                              )}
                              <Button
                                variant="default"
                                size="sm"
                                onClick={() => onMakePick(participant.id)}
                                disabled={!canPick || !isEligible}
                                title={
                                  !canPick
                                    ? "Not your turn"
                                    : !isEligible
                                      ? ineligibleReason
                                      : undefined
                                }
                              >
                                Draft
                              </Button>
                            </>
                          )}
                        </div>
                      </div>
                    )}
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </div>
    </div>
  );
});
