import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Text, ScrollArea, Box } from "@mantine/core";
import { BracketData } from "../types";
import { Bracket } from "./bracket";
import MatchDock from "./match-dock";
import useAppShellHeight from "@/hooks/use-appshell-height";
import { Match } from "@/features/matches/types";
import styles from "./styles.module.css";
import { Trans } from "@lingui/react/macro";

interface BracketViewProps {
  bracket: BracketData;
  showControls?: boolean;
  groupConfig?: {
    num_groups: number;
    advance_per_group: number;
  };
  renderMatch?: (match: Match) => React.ReactNode;
  bottomOffset?: number;
  nextUpMatchId?: string;
}

const BracketView: React.FC<BracketViewProps> = ({ bracket, showControls, groupConfig, renderMatch, bottomOffset, nextUpMatchId }) => {
  const height = useAppShellHeight();
  const viewportRef = useRef<HTMLDivElement>(null);
  const hasAutoScrolled = useRef(false);
  const orders = useMemo(() => {
    const map: Record<number, number> = {};
    bracket.winners.flat().forEach(match => map[match.lid] = match.order);
    bracket.losers.flat().forEach(match => map[match.lid] = match.order);
    return map;
  }, [bracket.winners, bracket.losers]);

  const [selectedLid, setSelectedLid] = useState<number | null>(null);
  const handleMatchTap = useCallback((match: Match) => {
    setSelectedLid((prev) => (prev === match.lid ? null : match.lid));
  }, []);
  const closeDock = useCallback(() => setSelectedLid(null), []);

  const selectedMatch = useMemo(() => {
    if (selectedLid == null) return null;
    return (
      [...bracket.winners.flat(), ...bracket.losers.flat()].find(
        (match) => match.lid === selectedLid
      ) ?? null
    );
  }, [bracket, selectedLid]);

  useEffect(() => {
    if (hasAutoScrolled.current) return;

    const matches = [...bracket.winners.flat(), ...bracket.losers.flat()].filter(
      (match) => !match.bye
    );
    const target = nextUpMatchId !== undefined
      ? matches.find((match) => match.id === nextUpMatchId)
      : matches.find((match) => match.status === "started") ??
        matches.find((match) => match.status === "ready");
    if (!target) return;

    const viewport = viewportRef.current;
    const element = viewport?.querySelector(`[data-match-lid="${target.lid}"]`);
    if (!viewport || !element) return;

    hasAutoScrolled.current = true;

    const viewportRect = viewport.getBoundingClientRect();
    const elementRect = element.getBoundingClientRect();
    const left =
      elementRect.left - viewportRect.left + viewport.scrollLeft - 40;
    const top =
      elementRect.top -
      viewportRect.top +
      viewport.scrollTop -
      (viewport.clientHeight - elementRect.height) / 2;

    viewport.scrollTo({
      left: Math.max(0, left),
      top: Math.max(0, top),
      behavior: window.matchMedia("(prefers-reduced-motion: reduce)").matches
        ? "auto"
        : "smooth",
    });
  }, [bracket, nextUpMatchId]);

  return <Box pos="relative">
    <ScrollArea
      viewportRef={viewportRef}
      h={`calc(${height})`}
      className={styles["bracket-container"]}
      style={{
        backgroundImage: `radial-gradient(circle, var(--mantine-color-default-border) 1px, transparent 1px)`,
        backgroundSize: "16px 16px",
        backgroundPosition: "0 0, 8px 8px",
      }}
    >
      <div>
        <Text fw={600} size="md" m={16}>
          <Trans>Winners Bracket</Trans>
        </Text>
        <Bracket rounds={bracket.winners} orders={orders} showControls={showControls} groupConfig={groupConfig} renderMatch={renderMatch} onMatchTap={handleMatchTap} selectedMatchLid={selectedLid} nextUpMatchId={nextUpMatchId} />
      </div>
      {bracket.losers && bracket.losers.length > 0 && bracket.losers.some(round => round.length > 0) && (
        <div>
          <Text fw={600} size="md" m={16}>
            <Trans>Losers Bracket</Trans>
          </Text>
        <Bracket rounds={bracket.losers} orders={orders} showControls={showControls} groupConfig={groupConfig} renderMatch={renderMatch} onMatchTap={handleMatchTap} selectedMatchLid={selectedLid} nextUpMatchId={nextUpMatchId} />
        </div>
      )}
      {bottomOffset ? <div style={{ height: bottomOffset }} /> : null}
    </ScrollArea>
    <MatchDock match={selectedMatch} onClose={closeDock} />
  </Box>
};

export default BracketView;
