import { memo, useState, useEffect, useRef } from "react";
import { DraftPickCell } from "~/components/draft/DraftPickCell";
import type { SeasonStatus } from "~/models/season";
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuTrigger,
} from "~/components/ui/context-menu";
import { formatClockTime, getTimerColorClass } from "~/lib/draft-timer";

const ROW_GAP = 6; // gap-1.5
const ANIMATION_MS = 300;

function getRoundIndices(round: number): [number, number] {
  if (round <= 2) return [0, 1];
  return [round - 2, round - 1];
}

export interface MiniDraftGridProps {
  draftSlots: Array<{
    id: string;
    draftOrder: number;
    team: {
      id: string;
      name: string;
      logoUrl?: string | null;
    };
  }>;
  draftGrid: Array<
    Array<{
      pickNumber: number;
      round: number;
      pickInRound: number;
      teamId: string;
      pick?: {
        participant: {
          name: string;
        };
        sport: {
          name: string;
        };
      };
    }>
  >;
  currentPick: number;
  currentRound: number;
  ownerMap?: Record<string, string>;
  teamTimers?: Record<string, number | undefined>;
  autodraftStatus?: Record<string, { isEnabled: boolean }>;
  seasonStatus?: SeasonStatus;
  draftPaused?: boolean;
  onForceAutopick?: (pickNumber: number, teamId: string) => void;
  onForceManualPickOpen?: (pickNumber: number, teamId: string) => void;
  onReplacePick?: (pickNumber: number, teamId: string) => void;
  onRollbackToPick?: (pickNumber: number) => void;
}

export const MiniDraftGrid = memo(function MiniDraftGrid({
  draftSlots,
  draftGrid,
  currentPick,
  currentRound,
  ownerMap = {},
  teamTimers = {},
  autodraftStatus = {},
  seasonStatus,
  draftPaused,
  onForceAutopick,
  onForceManualPickOpen,
  onReplacePick,
  onRollbackToPick,
}: MiniDraftGridProps) {
  const [displayedIndices, setDisplayedIndices] = useState<[number, number]>(() => getRoundIndices(currentRound));
  const [extraIndex, setExtraIndex] = useState<number | null>(null);
  const [sliding, setSliding] = useState(false);
  const animGenRef = useRef(0);
  const prevRoundRef = useRef(currentRound);
  const firstRowRef = useRef<HTMLDivElement>(null);
  const [rowHeight, setRowHeight] = useState(0);

  useEffect(() => {
    if (firstRowRef.current) {
      setRowHeight(firstRowRef.current.getBoundingClientRect().height);
    }
  }, [draftGrid]);

  useEffect(() => {
    const prev = prevRoundRef.current;
    prevRoundRef.current = currentRound;

    const newIndices = getRoundIndices(currentRound);
    const prevIndices = getRoundIndices(prev);

    if (newIndices[0] === prevIndices[0]) return;

    // Non-sequential jump or animation already running: snap and invalidate any in-flight animation
    if (newIndices[0] !== prevIndices[0] + 1 || animGenRef.current > 0) {
      animGenRef.current++; // invalidate any in-flight animation closure
      setDisplayedIndices(newIndices);
      setExtraIndex(null);
      setSliding(false);
      return;
    }

    const gen = ++animGenRef.current;
    setExtraIndex(newIndices[1]);

    // Two rAFs: first lets React flush the extra row to DOM, second starts the CSS transition
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        setSliding(true);

        setTimeout(() => {
          if (animGenRef.current !== gen) return; // interrupted by snap
          setDisplayedIndices(newIndices);
          setExtraIndex(null);
          setSliding(false);
          animGenRef.current = 0;
        }, ANIMATION_MS + 20);
      });
    });
  }, [currentRound]);

  if (draftGrid.length === 0) return null;

  // h-14 (56px) + gap-1.5 (6px) fallback until first measurement
  const effectiveRowHeight = rowHeight > 0 ? rowHeight : 56;

  const roundIndicesToRender: number[] = extraIndex !== null
    ? [displayedIndices[0], displayedIndices[1], extraIndex]
    : [displayedIndices[0], displayedIndices[1]];

  return (
    <div className="overflow-x-auto">
      <div className="inline-block min-w-full">
        {/* Team header */}
        <div className="flex gap-1.5 mb-1.5">
          {draftSlots.map((slot) => {
            const teamTime = teamTimers[slot.team.id];
            const isAutodraft = autodraftStatus[slot.team.id]?.isEnabled ?? false;
            return (
              <div key={slot.id} className="flex-1 min-w-20 text-center">
                <div className="text-xs font-medium truncate px-1 flex items-center justify-center gap-0.5">
                  {isAutodraft && (
                    <span className="inline-flex items-center justify-center h-3.5 w-3.5 text-[9px] font-bold text-white bg-black shrink-0">A</span>
                  )}
                  <span className="truncate">{ownerMap[slot.team.id] || slot.team.name}</span>
                </div>
                <div className={`text-xs font-mono px-1 ${getTimerColorClass(teamTime)}`}>
                  {formatClockTime(teamTime)}
                </div>
              </div>
            );
          })}
        </div>

        {/* Rows — clipped to 2-row height, slides to reveal new round */}
        <div style={{ height: `${effectiveRowHeight * 2 + ROW_GAP}px`, overflow: "hidden" }}>
          <div
            style={{
              display: "flex",
              flexDirection: "column",
              gap: `${ROW_GAP}px`,
              transform: sliding ? `translateY(-${effectiveRowHeight + ROW_GAP}px)` : "translateY(0)",
              transition: sliding ? `transform ${ANIMATION_MS}ms ease-in-out` : "none",
            }}
          >
            {roundIndicesToRender.map((roundIndex) => {
              if (roundIndex >= draftGrid.length) return null;
              const roundPicks = draftGrid[roundIndex];
              const round = roundIndex + 1;
              const isEvenRound = round % 2 === 0;
              const displayPicks = isEvenRound ? [...roundPicks].toReversed() : roundPicks;

              return (
                <div key={round} ref={roundIndex === displayedIndices[0] ? firstRowRef : undefined} className="flex gap-1.5 items-stretch flex-shrink-0">
                  {displayPicks.map((cell) => {
                    const isCurrent = cell.pickNumber === currentPick;
                    const isPicked = !!cell.pick;
                    const cellState = isPicked ? "picked" : isCurrent ? "current" : "upcoming";
                    const pickData = cell.pick
                      ? {
                          participant: { name: cell.pick.participant.name },
                          sport: { name: cell.pick.sport.name },
                        }
                      : undefined;

                    if (!isPicked && isCurrent && (onForceAutopick || onForceManualPickOpen)) {
                      return (
                        <ContextMenu key={cell.pickNumber}>
                          <ContextMenuTrigger asChild>
                            <DraftPickCell
                              pickNumber={cell.pickNumber}
                              round={cell.round}
                              pickInRound={cell.pickInRound}
                              state={cellState}
                              pick={pickData}
                              seasonStatus={seasonStatus}
                              draftPaused={draftPaused}
                              className="cursor-context-menu"
                            />
                          </ContextMenuTrigger>
                          <ContextMenuContent>
                            {onForceAutopick && (
                              <ContextMenuItem onClick={() => onForceAutopick(cell.pickNumber, cell.teamId)}>
                                Force Auto Pick
                              </ContextMenuItem>
                            )}
                            {onForceManualPickOpen && (
                              <ContextMenuItem onClick={() => onForceManualPickOpen(cell.pickNumber, cell.teamId)}>
                                Force Manual Pick
                              </ContextMenuItem>
                            )}
                          </ContextMenuContent>
                        </ContextMenu>
                      );
                    }

                    if (isPicked && (onReplacePick || onRollbackToPick)) {
                      return (
                        <ContextMenu key={cell.pickNumber}>
                          <ContextMenuTrigger asChild>
                            <DraftPickCell
                              pickNumber={cell.pickNumber}
                              round={cell.round}
                              pickInRound={cell.pickInRound}
                              state={cellState}
                              pick={pickData}
                              seasonStatus={seasonStatus}
                              draftPaused={draftPaused}
                              className="cursor-context-menu"
                            />
                          </ContextMenuTrigger>
                          <ContextMenuContent>
                            {onReplacePick && (
                              <ContextMenuItem onClick={() => onReplacePick(cell.pickNumber, cell.teamId)}>
                                Replace Pick
                              </ContextMenuItem>
                            )}
                            {onRollbackToPick && (
                              <ContextMenuItem
                                onClick={() => onRollbackToPick(cell.pickNumber)}
                                className="text-destructive focus:text-destructive"
                              >
                                Roll Back to This Pick
                              </ContextMenuItem>
                            )}
                          </ContextMenuContent>
                        </ContextMenu>
                      );
                    }

                    return (
                      <DraftPickCell
                        key={cell.pickNumber}
                        pickNumber={cell.pickNumber}
                        round={cell.round}
                        pickInRound={cell.pickInRound}
                        state={cellState}
                        pick={pickData}
                        seasonStatus={seasonStatus}
                        draftPaused={draftPaused}
                      />
                    );
                  })}
                </div>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
});
