"use client";

import { useMemo, useState, useCallback } from "react";
import { GroupTable, Match, Team, ThirdPlaceRow } from "@/lib/types";
import { ThirdAssignment, orderedRound } from "@/lib/bracket";
import { resolveBracket, ResolvedSide, ResolvedTie } from "@/lib/resolve-bracket";
import { STADIUMS, MATCH_STADIUMS, MATCH_DATES } from "@/lib/stadiums";
import Flag from "./Flag";

interface TipState { x: number; y: number; text: string }

function Side({
  s, prob, teams, onShowTip, onHideTip,
}: {
  s: ResolvedSide; prob?: number | null; teams: Team[];
  onShowTip: (text: string, x: number, y: number) => void;
  onHideTip: () => void;
}) {
  const team = s.teamId ? teams.find((t) => t.id === s.teamId) : undefined;
  const fix = s.teamId != null && !s.provisional;
  const hasTip = !!s.tooltip;

  return (
    <div
      className={`side ${s.isWinner ? "win" : ""} ${s.provisional ? "prov" : ""} ${fix ? "fix" : ""}`}
      {...(hasTip ? {
        onMouseEnter: (e: React.MouseEvent<HTMLDivElement>) => onShowTip(s.tooltip!, e.clientX, e.clientY),
        onMouseMove: (e: React.MouseEvent<HTMLDivElement>) => onShowTip(s.tooltip!, e.clientX, e.clientY),
        onMouseLeave: onHideTip,
      } : {})}
    >
      <span className="nm">
        {s.teamId ? (
          <>
            <Flag team={team} size={18} />
            <span className="tn">{s.label}</span>
            {s.provisional && <span className="prov-mark" title="vorläufig – Gruppe/Zuordnung noch nicht fix">≈</span>}
          </>
        ) : (
          <span className="lbl">{s.label}</span>
        )}
        {prob != null && prob > 0 && (
          <span className="prob">{Math.round(prob * 100)}%</span>
        )}
      </span>
      <span className="sc">{s.score != null ? s.score : "–"}</span>
    </div>
  );
}

function fmtMatchInfo(utcDate?: string, stadiumId?: string): string {
  if (!utcDate) return "";
  const d = new Date(utcDate);
  const dateStr = d.toLocaleDateString("de-DE", { day: "numeric", month: "numeric" });
  const timeStr = d.toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit" });
  const city = stadiumId ? STADIUMS[stadiumId]?.city : "";
  const parts = [`${dateStr}`, `${timeStr}`];
  if (city) parts.push(city);
  return parts.join(" ");
}

function Tie({
  tie, teams, isFinal, matchInfo, onShowTip, onHideTip,
}: {
  tie: ResolvedTie; teams: Team[]; isFinal?: boolean;
  matchInfo?: string;
  onShowTip: (text: string, x: number, y: number) => void;
  onHideTip: () => void;
}) {
  return (
    <div className={`tie ${isFinal ? "final-tie" : ""}`}>
      <div className="match-badge">{tie.matchNumber}</div>
      <div className="tie-head">
        {matchInfo || `Spiel ${tie.matchNumber}`}
      </div>
      <Side s={tie.home} prob={tie.prob?.home} teams={teams} onShowTip={onShowTip} onHideTip={onHideTip} />
      <Side s={tie.away} prob={tie.prob?.away} teams={teams} onShowTip={onShowTip} onHideTip={onHideTip} />
    </div>
  );
}

export default function Bracket({
  matches, teams, tables, thirds, assignment, annexResolved,
  preResolved,
}: {
  matches: Match[]; teams: Team[]; tables: GroupTable[];
  thirds: ThirdPlaceRow[]; assignment: ThirdAssignment | null; annexResolved: boolean;
  preResolved?: { r32: ResolvedTie[]; later: Record<number, ResolvedTie> };
}) {
  const { r32: r32Array, later } = preResolved ?? resolveBracket(
    matches, teams, tables, thirds, assignment, annexResolved,
  );

  const r32ByNum = new Map(r32Array.map((t) => [t.matchNumber, t]));

  // Slot-Nummer → formatierte Anzeige (Datum/Uhrzeit aus MATCH_DATES, Stadt aus MATCH_STADIUMS)
  const matchMeta = useMemo(() => {
    const meta = new Map<number, string>();
    for (let n = 73; n <= 104; n++) {
      const utcDate = MATCH_DATES[n];
      const stadiumId = MATCH_STADIUMS[n];
      const info = fmtMatchInfo(utcDate, stadiumId);
      if (info) meta.set(n, info);
    }
    return meta;
  }, []);

  const sfOrder = orderedRound([104]);
  const qfOrder = orderedRound(sfOrder);
  const r16Order = orderedRound(qfOrder);
  const r32Order = orderedRound(r16Order);

  const r32 = r32Order.map((n) => r32ByNum.get(n)).filter(Boolean) as ResolvedTie[];
  const r16 = r16Order.map((n) => later[n]).filter(Boolean);
  const qf = qfOrder.map((n) => later[n]).filter(Boolean);
  const sf = sfOrder.map((n) => later[n]).filter(Boolean);
  const fin = later[104];
  const third = later[103];

  const [tip, setTip] = useState<TipState | null>(null);
  const showTip = useCallback((text: string, x: number, y: number) => setTip({ x, y, text }), []);
  const hideTip = useCallback(() => setTip(null), []);

  return (
    <div>
      <div className="bracket-banner">
        <span className="k">Annex-C-Zuordnung der Drittplatzierten:</span>
        <span className="v">
          {annexResolved
            ? "aufgelöst — die acht Dritten sind den Gruppensiegern fest zugeteilt"
            : "noch offen — sobald die 8 besten Dritten feststehen, verbindet sich der Baum automatisch"}
        </span>
      </div>

      <div className="bracket-scroll">
        <div className="bracket">
          <div className="round">
            <div className="round-label">Letzte 32</div>
            <div className="round-matches">
              {r32.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} matchInfo={matchMeta.get(t.matchNumber)} onShowTip={showTip} onHideTip={hideTip} />)}
            </div>
          </div>
          <div className="round">
            <div className="round-label">Achtelfinale</div>
            <div className="round-matches">
              {r16.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} matchInfo={matchMeta.get(t.matchNumber)} onShowTip={showTip} onHideTip={hideTip} />)}
            </div>
          </div>
          <div className="round">
            <div className="round-label">Viertelfinale</div>
            <div className="round-matches">
              {qf.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} matchInfo={matchMeta.get(t.matchNumber)} onShowTip={showTip} onHideTip={hideTip} />)}
            </div>
          </div>
          <div className="round">
            <div className="round-label">Halbfinale</div>
            <div className="round-matches">
              {sf.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} matchInfo={matchMeta.get(t.matchNumber)} onShowTip={showTip} onHideTip={hideTip} />)}
            </div>
          </div>
          <div className="round">
            <div className="round-label">Finale</div>
            <div className="round-matches">
              {fin && <Tie tie={fin} teams={teams} isFinal matchInfo={matchMeta.get(fin.matchNumber)} onShowTip={showTip} onHideTip={hideTip} />}
              {third && (
                <div style={{ marginTop: 20 }}>
                  <div className="round-label" style={{ marginBottom: 8 }}>Spiel um Platz 3</div>
                  <Tie tie={third} teams={teams} matchInfo={matchMeta.get(third.matchNumber)} onShowTip={showTip} onHideTip={hideTip} />
                </div>
              )}
            </div>
          </div>
        </div>
      </div>

      <div className="legend">
        <span><i style={{ background: "var(--turf)" }} />Sieger / weiter</span>
        <span><i style={{ background: "var(--gold)" }} />Finale</span>
        <span><i className="leg-fix" />fix qualifiziert</span>
        <span><i className="leg-prov" />vorläufig (≈, nach aktueller Tabelle)</span>
        <span><i style={{ background: "var(--ink-faint)" }} />Platzhalter offen</span>
        <span>%-Werte: Polymarket-Wahrscheinlichkeit (falls verfügbar)</span>
      </div>

      {tip && (
        <div className="kobaum-tip" style={{ left: tip.x + 12, top: tip.y + 12 }}>
          {tip.text}
        </div>
      )}
    </div>
  );
}
