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 }>;
  connectedTeams?: Set<string>;
  seasonStatus?: SeasonStatus;
  draftPaused?: boolean;
  overnightPauseInfo?: { isActive: boolean; resumesAt: Date | null; pausedTeamIds?: Set<string> };
  onAdjustTimeBankOpen?: (teamId: string) => void;
  onSetAutodraftOpen?: (teamId: string) => void;
  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 = {},
  connectedTeams,
  seasonStatus,
  draftPaused,
  overnightPauseInfo,
  onAdjustTimeBankOpen,
  onSetAutodraftOpen,
  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);
  const scrollContainerRef = useRef<HTMLDivElement>(null);
  const currentCellRef = useRef<HTMLDivElement>(null);

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

  useEffect(() => {
    const container = scrollContainerRef.current;
    const cell = currentCellRef.current;
    if (!container || !cell) return;
    const containerRect = container.getBoundingClientRect();
    const cellRect = cell.getBoundingClientRect();
    const scrollLeft = container.scrollLeft + cellRect.left - containerRect.left - (containerRect.width - cellRect.width) / 2;
    container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
  }, [currentPick]);

  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;

  const hasHeaderMenu = !!(onAdjustTimeBankOpen || onSetAutodraftOpen);

  // 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]];

  const currentTeamId = draftGrid.flat().find((c) => c.pickNumber === currentPick)?.teamId;
  const isOvernightActive = overnightPauseInfo?.isActive ?? false;

  return (
    <div ref={scrollContainerRef} 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;
            const isConnected = connectedTeams ? connectedTeams.has(slot.team.id) : true;
            const isCurrentTeamOvernight = slot.team.id === currentTeamId
              ? isOvernightActive
              : (overnightPauseInfo?.pausedTeamIds?.has(slot.team.id) ?? false);

            const headerContent = (
              <>
                <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${!isConnected ? " italic text-muted-foreground" : ""}`}>
                    {ownerMap[slot.team.id] || slot.team.name}
                  </span>
                </div>
                <div className={`text-xs font-mono px-1 ${isCurrentTeamOvernight ? "text-muted-foreground" : getTimerColorClass(teamTime)}`}>
                  {isCurrentTeamOvernight ? `🌙 ${formatClockTime(teamTime)}` : formatClockTime(teamTime)}
                </div>
              </>
            );

            if (hasHeaderMenu) {
              return (
                <ContextMenu key={slot.id}>
                  <ContextMenuTrigger asChild>
                    <div className="flex-1 min-w-20 text-center cursor-context-menu">
                      {headerContent}
                    </div>
                  </ContextMenuTrigger>
                  <ContextMenuContent>
                    {onAdjustTimeBankOpen && (
                      <ContextMenuItem onClick={() => onAdjustTimeBankOpen(slot.team.id)}>
                        Adjust Time Bank...
                      </ContextMenuItem>
                    )}
                    {onSetAutodraftOpen && (
                      <ContextMenuItem onClick={() => onSetAutodraftOpen(slot.team.id)}>
                        Set Autodraft...
                      </ContextMenuItem>
                    )}
                  </ContextMenuContent>
                </ContextMenu>
              );
            }

            return (
              <div key={slot.id} className="flex-1 min-w-20 text-center">
                {headerContent}
              </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
                              ref={isCurrent ? currentCellRef : undefined}
                              pickNumber={cell.pickNumber}
                              round={cell.round}
                              pickInRound={cell.pickInRound}
                              state={cellState}
                              pick={pickData}
                              seasonStatus={seasonStatus}
                              draftPaused={draftPaused}
                              isOvernightPause={isCurrent && isOvernightActive}
                              resumesAt={isCurrent && isOvernightActive && overnightPauseInfo?.resumesAt ? overnightPauseInfo.resumesAt : undefined}
                              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}
                        ref={isCurrent ? currentCellRef : undefined}
                        pickNumber={cell.pickNumber}
                        round={cell.round}
                        pickInRound={cell.pickInRound}
                        state={cellState}
                        pick={pickData}
                        seasonStatus={seasonStatus}
                        draftPaused={draftPaused}
                        isOvernightPause={isCurrent && isOvernightActive}
                        resumesAt={isCurrent && isOvernightActive && overnightPauseInfo?.resumesAt ? overnightPauseInfo.resumesAt : undefined}
                      />
                    );
                  })}
                </div>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
});
