import { avatarColor } from "~/lib/avatar-colors";
import { BRACKT_GRADIENT } from "~/lib/brand";

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;
export const SLOT_WIDTH = 2 * COLUMN_WIDTH + CONNECTOR_WIDTH;
export const LABEL_HEIGHT = 32;
export const CARD_GAP = 14;
export const DESIRED_CARD_HEIGHT = 112;
export const MAX_CARD_HEIGHT = 140;


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.5 px-2 pl-[7px] ml-2",
          isWinner && isOwned ? "border border-electric/50 bg-electric/8 rounded-md mr-2 my-0.5 self-stretch py-1" :
          isWinner ? "border border-white/15 bg-white/5 rounded-md mr-2 my-0.5 self-stretch py-1" : "",
        ].filter(Boolean).join(" ")}>
          {/* Manager avatar — always present for alignment; empty box when unowned */}
          <div
            className="shrink-0 rounded-[3px] flex items-center justify-center text-[8px] font-bold"
            style={{
              width: 18,
              height: 18,
              background: ownership ? "#000" : "transparent",
              color: ownership ? avatarColor(ownership.teamName) : undefined,
            }}
          >
            {ownership &&
              ownership.teamName
                .split(/\s+/)
                .slice(0, 2)
                .map((w) => w[0]?.toUpperCase() ?? "")
                .join("")}
          </div>

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

            {/* Owner name below participant name */}
            {showOwner && !isTbd && ownership && (
              <span className="text-[10px] text-muted-foreground truncate block leading-none">
                {ownership.ownerName ?? ownership.teamName}
              </span>
            )}
          </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>;
}

export 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: BRACKT_GRADIENT }
    : 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={p1Ownership}
          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={p2Ownership}
          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[] = [];

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

  // Use halving U-shapes only when prev > 1 (avoids false-positive 1→1 side branches like 3PG→Finals)
  if (nextMatches.length === Math.ceil(currentMatches.length / 2) && currentMatches.length > 1) {
    // Standard single-elimination halving: U-shape connectors
    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;
        paths.push(`M 0 ${topY} H ${mid} V ${botY} H 0`);
        paths.push(`M ${mid} ${midY} H ${CONNECTOR_WIDTH}`);
      } else {
        paths.push(`M 0 ${topY} H ${CONNECTOR_WIDTH}`);
      }
    }
  } else {
    // Non-standard (byes, play-ins, etc.): trace winners by participantId
    const winnerToIdx = new Map<string, number>();
    currentMatches.forEach((m, idx) => {
      if (m.winnerId) winnerToIdx.set(m.winnerId, idx);
    });

    nextMatches.forEach((nextMatch, nextIdx) => {
      const destY = nextIdx * nextSlotH + nextSlotH / 2;
      for (const pId of [nextMatch.participant1Id, nextMatch.participant2Id]) {
        if (!pId) continue;
        const srcIdx = winnerToIdx.get(pId);
        if (srcIdx === undefined) continue;
        const srcY = srcIdx * currentSlotH + currentSlotH / 2;
        paths.push(`M 0 ${srcY} H ${mid} V ${destY} 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="rgb(255 255 255 / 22%)" strokeWidth={1.5} />
        ))}
      </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;
  transitionDuration?: number;
}

export function TreeColumns({
  visibleRounds,
  matchesByRound,
  ownershipMap,
  userParticipantIds,
  bracketHeight,
  transitionDuration,
}: TreeColumnsProps) {
  const tr = transitionDuration ? `${transitionDuration}ms ease` : undefined;
  return (
    <div style={{ display: "flex", width: "100%", height: bracketHeight + LABEL_HEIGHT, transition: tr ? `height ${tr}` : undefined }}>
      {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, transition: tr ? `height ${tr}` : undefined }}>
                {roundMatches.map((match, matchIdx) => (
                  <div
                    key={match.id}
                    style={{
                      position: "absolute",
                      top: matchIdx * slotHeight + cardTop,
                      left: 0,
                      right: 0,
                      height: cardHeight,
                      transition: tr ? `top ${tr}, height ${tr}` : undefined,
                    }}
                  >
                    <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>;
  thirdPlaceRound?: string;
}

export function BracketTreeView({
  rounds,
  matchesByRound,
  ownershipMap,
  userParticipantIds,
  thirdPlaceRound,
}: BracketTreeViewProps) {
  const mainRounds = thirdPlaceRound ? rounds.filter((r) => r !== thirdPlaceRound) : rounds;
  const thirdPlaceMatch = thirdPlaceRound ? (matchesByRound.get(thirdPlaceRound) ?? [])[0] : undefined;

  const maxMatches = Math.max(...mainRounds.map((r) => matchesByRound.get(r)?.length ?? 0), 1);
  const bracketHeight = maxMatches * (DESIRED_CARD_HEIGHT + CARD_GAP);
  const minWidth = mainRounds.length * COLUMN_WIDTH + Math.max(0, mainRounds.length - 1) * CONNECTOR_WIDTH;

  return (
    <div
      className="w-full overflow-x-auto"
      style={{ minHeight: bracketHeight + LABEL_HEIGHT + 2 }}
    >
      <div style={{ minWidth }}>
        <TreeColumns
          visibleRounds={mainRounds}
          matchesByRound={matchesByRound}
          ownershipMap={ownershipMap}
          userParticipantIds={userParticipantIds}
          bracketHeight={bracketHeight}
        />
        {thirdPlaceMatch && (
          <div style={{ display: "flex", paddingTop: 20 }}>
            <div style={{ flex: 1 }} />
            <div style={{ minWidth: COLUMN_WIDTH }}>
              <div
                className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground text-center"
                style={{ height: LABEL_HEIGHT, display: "flex", alignItems: "center", justifyContent: "center" }}
              >
                3rd Place
              </div>
              <div style={{ height: Math.min(DESIRED_CARD_HEIGHT, MAX_CARD_HEIGHT) }}>
                <BracketMatchSlot
                  match={thirdPlaceMatch}
                  slotHeight={Math.min(DESIRED_CARD_HEIGHT, MAX_CARD_HEIGHT)}
                  ownershipMap={ownershipMap}
                  userParticipantIds={userParticipantIds}
                />
              </div>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

