import { useState } from "react";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { Button } from "~/components/ui/button";

export interface BracketMatch {
  id: string;
  round: string;
  matchNumber: number;
  participant1Id: string | null;
  participant2Id: string | null;
  winnerId: string | null;
  loserId: string | null;
  isComplete: boolean;
  participant1Score: string | null;
  participant2Score: string | null;
  isScoring?: boolean;
  participant1?: { id: string; name: string } | null;
  participant2?: { id: string; name: string } | null;
  winner?: { id: string; name: string } | null;
  loser?: { id: string; name: string } | null;
}

export interface BracketOwnership {
  participantId: string;
  teamName: string;
  teamId: string;
  ownerName?: string;
}

const COLUMN_WIDTH = 152;
const CONNECTOR_WIDTH = 24;
const LABEL_HEIGHT = 32;
const CARD_GAP = 14;         // vertical gap between cards (split top/bottom)
const DESIRED_CARD_HEIGHT = 112; // target card height — tall enough to show owner info
const MAX_CARD_HEIGHT = 140;    // cap for sparse later rounds

// Avatar color palette (matches TeamOwnerBadge)
const AVATAR_COLORS = ["#adf661", "#2ce1c1", "#8b5cf6", "#f59e0b", "#ef4444", "#3b82f6"];
function hashName(name: string): number {
  let h = 0;
  for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) & 0xffff;
  return h;
}
function avatarColor(name: string) {
  return AVATAR_COLORS[hashName(name) % AVATAR_COLORS.length];
}

function formatScore(score: string | null): string | null {
  if (!score) return null;
  const n = parseFloat(score);
  if (isNaN(n)) return null;
  return Number.isInteger(n) ? String(n) : n.toFixed(1);
}

// ─── Match Slot ──────────────────────────────────────────────────────────────

interface ParticipantRowProps {
  name: string | null;
  isTbd: boolean;
  isWinner: boolean;
  isLoser: boolean;
  isOwned: boolean;
  ownership: BracketOwnership | null;
  score: string | null;
  rowHeight: number;
  showScore: boolean;
  showOwner: boolean;
  showText: boolean;
}

function ParticipantRow({
  name,
  isTbd,
  isWinner,
  isLoser,
  isOwned,
  ownership,
  score,
  rowHeight,
  showScore,
  showOwner,
  showText,
}: ParticipantRowProps) {
  const formattedScore = formatScore(score);

  return (
    <div
      className="relative flex items-center overflow-hidden"
      style={{ height: rowHeight }}
    >
      {showText && (
        <div className={[
          "flex items-center flex-1 min-w-0 gap-1 px-2 pl-[7px] ml-2",
          isWinner ? "border border-white/15 bg-white/5 rounded-md mr-2 my-0.5 self-stretch py-1" : "",
        ].filter(Boolean).join(" ")}>
          {/* Electric dot for user's pick (when not winner) */}
          {isOwned && !isWinner && showText && (
            <span
              className="shrink-0 rounded-full"
              style={{ width: 5, height: 5, background: "#2ce1c1" }}
            />
          )}

          <div className="flex-1 min-w-0">
            <span
              className={[
                "text-[13px] leading-tight block truncate",
                isTbd ? "text-muted-foreground/50 italic" : "",
                isLoser ? "text-muted-foreground line-through" : "",
                isOwned && !isLoser ? "text-electric font-medium" : "",
                isWinner ? "font-semibold" : "",
              ]
                .filter(Boolean)
                .join(" ")}
            >
              {name ?? "TBD"}
            </span>

            {/* Owner info row */}
            {showOwner && !isTbd && ownership && (
              <div className="flex items-center gap-1 mt-0.5">
                <div
                  className="shrink-0 rounded-[2px] flex items-center justify-center text-[8px] font-bold"
                  style={{
                    width: 14,
                    height: 14,
                    background: "#000",
                    color: avatarColor(ownership.teamName),
                  }}
                >
                  {ownership.teamName
                    .split(/\s+/)
                    .slice(0, 2)
                    .map((w) => w[0]?.toUpperCase() ?? "")
                    .join("")}
                </div>
                <span className="text-[10px] text-muted-foreground truncate">
                  {ownership.ownerName ?? ownership.teamName}
                </span>
              </div>
            )}
          </div>

          {/* Score */}
          {showScore && formattedScore && (
            <span
              className={[
                "shrink-0 text-xs tabular-nums font-medium ml-auto pl-1",
                isLoser ? "text-muted-foreground/60" : "",
                isWinner ? "text-yellow-400" : "",
              ]
                .filter(Boolean)
                .join(" ")}
            >
              {formattedScore}
            </span>
          )}
        </div>
      )}
    </div>
  );
}

interface BracketMatchSlotProps {
  match: BracketMatch;
  slotHeight: number;
  ownershipMap: Map<string, BracketOwnership>;
  userParticipantIds: Set<string>;
}

function BracketMatchSlot({
  match,
  slotHeight,
  ownershipMap,
  userParticipantIds,
}: BracketMatchSlotProps) {
  const rowHeight = slotHeight / 2;
  const showText = rowHeight >= 10;
  const showScore = rowHeight >= 20 && (!!match.participant1Score || match.isComplete);
  const showOwner = rowHeight >= 36;

  const p1Id = match.participant1Id;
  const p2Id = match.participant2Id;
  const p1IsWinner = match.isComplete && match.winnerId === p1Id;
  const p2IsWinner = match.isComplete && match.winnerId === p2Id;
  const p1IsLoser = match.isComplete && match.loserId === p1Id;
  const p2IsLoser = match.isComplete && match.loserId === p2Id;
  const p1IsOwned = !!(p1Id && userParticipantIds.has(p1Id));
  const p2IsOwned = !!(p2Id && userParticipantIds.has(p2Id));
  const matchHasOwned = p1IsOwned || p2IsOwned;
  const isTbd1 = !p1Id;
  const isTbd2 = !p2Id;

  const p1Ownership = p1Id ? ownershipMap.get(p1Id) ?? null : null;
  const p2Ownership = p2Id ? ownershipMap.get(p2Id) ?? null : null;

  // Corona glow: gradient for complete matches, electric for user's picks, subtle white for pending
  const coronaStyle: React.CSSProperties = match.isComplete
    ? { background: "linear-gradient(to bottom, #adf661, #2ce1c1)" }
    : matchHasOwned
    ? { background: "rgba(44, 225, 193, 0.4)" }
    : { background: "rgba(255, 255, 255, 0.07)" };

  const INSET = Math.max(1, Math.min(2, Math.floor(slotHeight / 20)));

  return (
    <div className="relative overflow-hidden" style={{ height: slotHeight }}>
      {/* Corona layer — left-2 matches card borderRadius to prevent gradient bleed at left corners */}
      <div className="absolute left-2 right-0 rounded-lg" style={{ ...coronaStyle, top: INSET - 2, bottom: INSET - 2 }} />

      {/* Inner card, inset on right to expose corona glow strip */}
      <div
        className="absolute flex flex-col overflow-hidden"
        style={{
          top: 0,
          right: INSET + 2,
          bottom: 0,
          left: 0,
          borderRadius: 8,
          background: "var(--color-muted)",
          paddingTop: INSET,
          paddingBottom: INSET,
        }}
      >
        <ParticipantRow
          name={match.participant1?.name ?? null}
          isTbd={isTbd1}
          isWinner={p1IsWinner}
          isLoser={p1IsLoser}
          isOwned={p1IsOwned}
          ownership={showOwner ? p1Ownership : null}
          score={match.participant1Score}
          rowHeight={rowHeight - INSET}
          showScore={showScore}
          showOwner={showOwner}
          showText={showText}
        />
        <ParticipantRow
          name={match.participant2?.name ?? null}
          isTbd={isTbd2}
          isWinner={p2IsWinner}
          isLoser={p2IsLoser}
          isOwned={p2IsOwned}
          ownership={showOwner ? p2Ownership : null}
          score={match.participant2Score}
          rowHeight={rowHeight - INSET}
          showScore={showScore}
          showOwner={showOwner}
          showText={showText}
        />
      </div>
    </div>
  );
}

// ─── Per-pair connector column ────────────────────────────────────────────────

interface ConnectorColumnProps {
  currentMatches: BracketMatch[];
  nextMatches: BracketMatch[];
  bracketHeight: number;
}

function ConnectorColumn({ currentMatches, nextMatches, bracketHeight }: ConnectorColumnProps) {
  const mid = CONNECTOR_WIDTH / 2;
  const paths: string[] = [];

  if (nextMatches.length === Math.ceil(currentMatches.length / 2)) {
    const currentSlotH = bracketHeight / Math.max(currentMatches.length, 1);
    const nextSlotH = bracketHeight / Math.max(nextMatches.length, 1);

    for (let k = 0; k < nextMatches.length; k++) {
      const topY = (2 * k) * currentSlotH + currentSlotH / 2;
      const midY = k * nextSlotH + nextSlotH / 2;
      const botIdx = 2 * k + 1;

      if (botIdx < currentMatches.length) {
        const botY = botIdx * currentSlotH + currentSlotH / 2;
        // U-shape from two source midpoints; horizontal out to next column
        paths.push(`M 0 ${topY} H ${mid} V ${botY} H 0`);
        paths.push(`M ${mid} ${midY} H ${CONNECTOR_WIDTH}`);
      } else {
        // Odd last match: straight line through
        paths.push(`M 0 ${topY} H ${CONNECTOR_WIDTH}`);
      }
    }
  }

  return (
    <div style={{ flex: `0 0 ${CONNECTOR_WIDTH}px`, position: "relative" }}>
      <svg
        style={{
          position: "absolute",
          top: LABEL_HEIGHT,
          left: 0,
          width: CONNECTOR_WIDTH,
          height: bracketHeight,
          overflow: "visible",
          pointerEvents: "none",
        }}
      >
        {paths.map((d) => (
          <path key={d} d={d} fill="none" stroke="hsl(var(--border))" strokeWidth={1} />
        ))}
      </svg>
    </div>
  );
}

// ─── Tree columns (shared by full + paginated) ───────────────────────────────

interface TreeColumnsProps {
  visibleRounds: string[];
  matchesByRound: Map<string, BracketMatch[]>;
  ownershipMap: Map<string, BracketOwnership>;
  userParticipantIds: Set<string>;
  bracketHeight: number;
}

function TreeColumns({
  visibleRounds,
  matchesByRound,
  ownershipMap,
  userParticipantIds,
  bracketHeight,
}: TreeColumnsProps) {
  return (
    <div style={{ display: "flex", width: "100%", height: bracketHeight + LABEL_HEIGHT }}>
      {visibleRounds.map((round, ri) => {
        const roundMatches = matchesByRound.get(round) ?? [];
        const slotHeight = bracketHeight / Math.max(roundMatches.length, 1);
        const cardHeight = Math.min(slotHeight - CARD_GAP, MAX_CARD_HEIGHT);
        const cardTop = (slotHeight - cardHeight) / 2;
        const nextRound = ri < visibleRounds.length - 1 ? visibleRounds[ri + 1] : null;
        const nextMatches = nextRound ? (matchesByRound.get(nextRound) ?? []) : [];

        return (
          <div key={round} style={{ display: "contents" }}>
            {/* Round column */}
            <div style={{ flex: "1 1 0", minWidth: COLUMN_WIDTH, position: "relative" }}>
              <div
                className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground truncate text-center"
                style={{ height: LABEL_HEIGHT, display: "flex", alignItems: "center", justifyContent: "center" }}
              >
                {round}
              </div>

              <div style={{ position: "relative", height: bracketHeight }}>
                {roundMatches.map((match, matchIdx) => (
                  <div
                    key={match.id}
                    style={{
                      position: "absolute",
                      top: matchIdx * slotHeight + cardTop,
                      left: 0,
                      right: 0,
                      height: cardHeight,
                    }}
                  >
                    <BracketMatchSlot
                      match={match}
                      slotHeight={cardHeight}
                      ownershipMap={ownershipMap}
                      userParticipantIds={userParticipantIds}
                    />
                  </div>
                ))}
              </div>
            </div>

            {/* Connector between this column and the next */}
            {nextRound && (
              <ConnectorColumn
                currentMatches={roundMatches}
                nextMatches={nextMatches}
                bracketHeight={bracketHeight}
              />
            )}
          </div>
        );
      })}
    </div>
  );
}

// ─── Full desktop tree ────────────────────────────────────────────────────────

interface BracketTreeViewProps {
  rounds: string[];
  matchesByRound: Map<string, BracketMatch[]>;
  ownershipMap: Map<string, BracketOwnership>;
  userParticipantIds: Set<string>;
}

export function BracketTreeView({
  rounds,
  matchesByRound,
  ownershipMap,
  userParticipantIds,
}: BracketTreeViewProps) {
  const maxMatches = Math.max(...rounds.map((r) => matchesByRound.get(r)?.length ?? 0), 1);
  const bracketHeight = maxMatches * (DESIRED_CARD_HEIGHT + CARD_GAP);
  const minWidth = rounds.length * COLUMN_WIDTH + Math.max(0, rounds.length - 1) * CONNECTOR_WIDTH;

  return (
    <div
      className="w-full overflow-x-auto"
      style={{ minHeight: bracketHeight + LABEL_HEIGHT + 2 }}
    >
      <div style={{ minWidth }}>
        <TreeColumns
          visibleRounds={rounds}
          matchesByRound={matchesByRound}
          ownershipMap={ownershipMap}
          userParticipantIds={userParticipantIds}
          bracketHeight={bracketHeight}
        />
      </div>
    </div>
  );
}

// ─── Paginated mobile tree ────────────────────────────────────────────────────

interface BracketTreePaginatedProps {
  rounds: string[];
  matchesByRound: Map<string, BracketMatch[]>;
  ownershipMap: Map<string, BracketOwnership>;
  userParticipantIds: Set<string>;
  /** Index of the first scoring round — default page starts here */
  firstScoringRoundIdx?: number;
}

export function BracketTreePaginated({
  rounds,
  matchesByRound,
  ownershipMap,
  userParticipantIds,
  firstScoringRoundIdx,
}: BracketTreePaginatedProps) {
  // Default to showing around the first scoring round
  const defaultPage = Math.max(
    0,
    Math.min(
      firstScoringRoundIdx !== undefined
        ? Math.max(0, firstScoringRoundIdx - 1)
        : rounds.length - 2,
      rounds.length - 2,
    ),
  );
  const [pageStart, setPageStart] = useState(defaultPage);

  const visibleRounds = rounds.slice(pageStart, pageStart + 2);
  const canGoLeft = pageStart > 0;
  const canGoRight = pageStart + 2 < rounds.length;

  const maxMatchesInView = Math.max(...visibleRounds.map((r) => matchesByRound.get(r)?.length ?? 0), 1);
  const bracketHeight = maxMatchesInView * (DESIRED_CARD_HEIGHT + CARD_GAP);

  return (
    <div>
      {/* Round tab navigation */}
      <div className="flex items-center gap-1 mb-3 overflow-x-auto pb-1">
        {rounds.map((round, ri) => {
          const isActive = ri >= pageStart && ri < pageStart + 2;
          return (
            <button
              key={round}
              onClick={() => setPageStart(Math.min(ri, rounds.length - 2))}
              className={[
                "shrink-0 px-2 py-1 rounded text-[10px] font-medium uppercase tracking-wide transition-colors",
                isActive
                  ? "bg-electric/15 text-electric border border-electric/30"
                  : "text-muted-foreground border border-transparent hover:text-foreground hover:border-border",
              ].join(" ")}
            >
              {round}
            </button>
          );
        })}
      </div>

      {/* Bracket columns */}
      <div style={{ minHeight: bracketHeight + LABEL_HEIGHT + 2 }}>
        <TreeColumns
          visibleRounds={visibleRounds}
          matchesByRound={matchesByRound}
          ownershipMap={ownershipMap}
          userParticipantIds={userParticipantIds}
          bracketHeight={bracketHeight}
        />
      </div>

      {/* Prev / Next navigation */}
      <div className="flex items-center justify-between mt-3">
        <Button
          variant="outline"
          size="sm"
          onClick={() => setPageStart((p) => Math.max(0, p - 1))}
          disabled={!canGoLeft}
          className="gap-1 text-xs"
        >
          <ChevronLeft className="h-3 w-3" />
          {canGoLeft ? rounds[pageStart - 1] : "—"}
        </Button>

        <span className="text-xs text-muted-foreground">
          {visibleRounds[0]}
          {visibleRounds[1] ? ` → ${visibleRounds[1]}` : ""}
        </span>

        <Button
          variant="outline"
          size="sm"
          onClick={() => setPageStart((p) => Math.min(rounds.length - 2, p + 1))}
          disabled={!canGoRight}
          className="gap-1 text-xs"
        >
          {canGoRight ? rounds[pageStart + 2] : "—"}
          <ChevronRight className="h-3 w-3" />
        </Button>
      </div>
    </div>
  );
}
