"use client";

import { useState, useMemo, useCallback, useEffect } from "react";
import { Match, Team } from "@/lib/types";
import { computeGroupTables, computeThirdPlaceTable } from "@/lib/standings";
import { qualifiedThirdGroups, resolveAnnexC, LATER_ROUNDS } from "@/lib/bracket";
import { resolveBracket, ResolvedTie } from "@/lib/resolve-bracket";
import {
  loadOverrides, saveOverrides, buildSimMatches,
  defaultScore, SimOverrides,
} from "@/lib/simulation";
import Bracket from "./Bracket";
import ThirdPlace from "./ThirdPlace";
import Flag from "./Flag";

function teamById(teams: Team[], id: string | null) {
  return id ? teams.find((t) => t.id === id) : undefined;
}

function fmtDate(iso: string): string {
  const d = new Date(iso);
  return d.toLocaleString("de-DE", {
    weekday: "short", day: "2-digit", month: "2-digit",
    hour: "2-digit", minute: "2-digit",
  });
}

// Label für die Spielphase in der Liste
function phaseLabel(match: Match): string {
  if (match.stage === "GROUP" && match.group) return `Gruppe ${match.group}`;
  if (match.stage === "R32") return "Sechzehntelfinale";
  if (match.stage === "R16") return "Achtelfinale";
  if (match.stage === "QF") return "Viertelfinale";
  if (match.stage === "SF") return "Halbfinale";
  if (match.stage === "3RD") return "Spiel um Platz 3";
  if (match.stage === "FINAL") return "Finale";
  return match.stage;
}

export default function Simulation({ teams, matches }: { teams: Team[]; matches: Match[] }) {
  const [overrides, setOverrides] = useState<SimOverrides>({});

  useEffect(() => {
    setOverrides(loadOverrides());
  }, []);

  const handleScore = useCallback((matchId: string, homeScore: number, awayScore: number) => {
    setOverrides((prev) => {
      const next = { ...prev, [matchId]: { homeScore, awayScore } };
      saveOverrides(next);
      return next;
    });
  }, []);

  const handleReset = useCallback(() => {
    setOverrides({});
    saveOverrides({});
  }, []);

  const handleClear = useCallback((matchId: string) => {
    setOverrides((prev) => {
      const next = { ...prev };
      delete next[matchId];
      saveOverrides(next);
      return next;
    });
  }, []);

  // ---- Simulations-Pipeline ----
  const simMatches = useMemo(() => buildSimMatches(matches, overrides), [matches, overrides]);
  const simTables = useMemo(() => computeGroupTables(teams, simMatches), [teams, simMatches]);
  const simThirds = useMemo(() => computeThirdPlaceTable(simTables), [simTables]);
  const simQGroups = useMemo(() => qualifiedThirdGroups(simThirds), [simThirds]);
  const simAnnex = useMemo(
    () => (simQGroups.length === 8 ? resolveAnnexC(simQGroups) : null),
    [simQGroups],
  );
  const simAnnexResolved = simAnnex != null;

  const simBracket = useMemo(
    () => resolveBracket(simMatches, teams, simTables, simThirds, simAnnex, simAnnexResolved, true),
    [simMatches, teams, simTables, simThirds, simAnnex, simAnnexResolved],
  );

  // Echte Tabellen/Bracket für fix/provisional-Flags (nur tatsächlich FINISHED).
  const realTables = useMemo(() => computeGroupTables(teams, matches), [teams, matches]);
  const realThirds = useMemo(() => computeThirdPlaceTable(realTables), [realTables]);
  const realQGroups = useMemo(() => qualifiedThirdGroups(realThirds), [realThirds]);
  const realAnnex = useMemo(
    () => (realQGroups.length === 8 ? resolveAnnexC(realQGroups) : null),
    [realQGroups],
  );
  const realBracket = useMemo(
    () => resolveBracket(matches, teams, realTables, realThirds, realAnnex, realAnnex != null),
    [matches, teams, realTables, realThirds, realAnnex],
  );

  // R32: provisional-Flags aus dem echten Bracket übernehmen.
  const realProvisional = useMemo(() => {
    const m = new Map<number, { home: boolean; away: boolean }>();
    for (const tie of realBracket.r32) {
      m.set(tie.matchNumber, { home: tie.home.provisional, away: tie.away.provisional });
    }
    return m;
  }, [realBracket]);

  // Folgerunden: decided-Flags aus echten Matches (status === FINISHED).
  const realDecided = useMemo(() => {
    const m = new Map<number, boolean>();
    for (const mt of matches) {
      if (mt.group == null && mt.matchNumber >= 73) {
        m.set(mt.matchNumber, mt.status === "FINISHED");
      }
    }
    return m;
  }, [matches]);

  // Sim-Bracket mit echten provisional-Flags mergen (inkl. Tooltip-Korrektur).
  const preResolved = useMemo(() => {
    const fixTooltip = (t: string | null, prov: boolean): string | null => {
      if (!t) return t;
      if (prov) return t.startsWith("aktuell ") ? t : `aktuell ${t}`;
      return t.startsWith("aktuell ") ? t.slice(8) : t;
    };

    const r32Fixed: ResolvedTie[] = simBracket.r32.map((tie) => {
      const rp = realProvisional.get(tie.matchNumber);
      if (!rp) return tie;
      return {
        ...tie,
        home: { ...tie.home, provisional: rp.home, tooltip: fixTooltip(tie.home.tooltip, rp.home) },
        away: { ...tie.away, provisional: rp.away, tooltip: fixTooltip(tie.away.tooltip, rp.away) },
      };
    });

    const laterFixed: Record<number, ResolvedTie> = {};
    for (const km of LATER_ROUNDS) {
      const tie = simBracket.later[km.matchNumber];
      if (!tie) continue;
      const homeProv = !(realDecided.get(km.fromHome) ?? false);
      const awayProv = !(realDecided.get(km.fromAway) ?? false);
      laterFixed[km.matchNumber] = {
        ...tie,
        home: { ...tie.home, provisional: homeProv },
        away: { ...tie.away, provisional: awayProv },
      };
    }

    return { r32: r32Fixed, later: laterFixed };
  }, [simBracket, realProvisional, realDecided]);

  // ---- Eingabeliste: offene Spiele aus dem echten Feed ----
  const openMatches = useMemo(
    () =>
      matches
        .filter((m) => m.status !== "FINISHED")
        .sort((a, b) => +new Date(a.utcDate) - +new Date(b.utcDate)),
    [matches],
  );

  const groupPhase = openMatches.filter((m) => m.stage === "GROUP");
  const koPhase = openMatches.filter((m) => m.stage !== "GROUP");

  // KO-Eingaben erst freigeben, wenn alle Gruppenspiele beendet sind.
  const groupPhaseComplete = matches
    .filter((m) => m.group != null)
    .every((m) => m.status === "FINISHED");

  const hasChanges = Object.keys(overrides).length > 0;

  return (
    <div>
      <div className="notice" style={{ marginBottom: 20 }}>
        Simulation — Ergebnisse frei wählbar, beeinflusst nicht die echten Daten.
        Alle ungespielten Spiele sind vorbelegt mit dem Polymarket-Favoriten.
        Eingaben werden im Browser gespeichert.
      </div>

      {/* ---- Eingabeliste ---- */}
      <div style={{ marginBottom: 28 }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 14 }}>
          <h3 style={{ fontFamily: "var(--font-display)", fontSize: 15, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--ink-dim)", margin: 0 }}>
            Offene Spiele ({openMatches.length})
          </h3>
          {hasChanges && (
            <button
              onClick={handleReset}
              style={{
                fontFamily: "var(--font-mono)", fontSize: 11,
                color: "var(--ink-faint)", background: "var(--bg-card)",
                border: "1px solid var(--line)", borderRadius: "var(--radius-sm)",
                padding: "5px 12px", cursor: "pointer",
              }}
            >
              Auf Polymarket-Defaults zurücksetzen
            </button>
          )}
        </div>

        {groupPhase.length > 0 && (
          <div style={{ marginBottom: 16 }}>
            <div style={{ fontFamily: "var(--font-display)", fontSize: 12, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--ink-faint)", marginBottom: 8 }}>
              Gruppenphase
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
              {groupPhase.map((m) => (
                <SimRow key={m.id} match={m} teams={teams} overrides={overrides} onScore={handleScore} onClear={handleClear} />
              ))}
            </div>
          </div>
        )}

        {koPhase.length > 0 && (
          <div>
            <div style={{ fontFamily: "var(--font-display)", fontSize: 12, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--ink-faint)", marginBottom: 8 }}>
              K.o.-Phase
            </div>
            {groupPhaseComplete ? (
              <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
                {koPhase.map((m) => (
                  <SimRow key={m.id} match={m} teams={teams} overrides={overrides} onScore={handleScore} onClear={handleClear} />
                ))}
              </div>
            ) : (
              <div className="notice" style={{ fontSize: 13 }}>
                K.o.-Spiele werden zur Eingabe freigegeben, sobald die Gruppenphase abgeschlossen ist.
              </div>
            )}
          </div>
        )}
      </div>

      {/* ---- Drittplatzierte (simuliert) ---- */}
      <h3 style={{ fontFamily: "var(--font-display)", fontSize: 15, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--ink-dim)", margin: "0 0 12px" }}>
        Drittplatzierte (simuliert)
      </h3>
      <ThirdPlace rows={simThirds} teams={teams} />

      {/* ---- Simulierter K.o.-Baum ---- */}
      <h3 style={{ fontFamily: "var(--font-display)", fontSize: 15, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--ink-dim)", margin: "28px 0 12px" }}>
        Simulierter K.o.-Baum
      </h3>
      <Bracket
        matches={simMatches}
        teams={teams}
        tables={simTables}
        thirds={simThirds}
        assignment={simAnnex}
        annexResolved={simAnnexResolved}
        preResolved={preResolved}
      />
    </div>
  );
}

// ---- Einzelne Eingabezeile ----
function SimRow({
  match, teams, overrides, onScore, onClear,
}: {
  match: Match; teams: Team[]; overrides: SimOverrides; onScore: (id: string, h: number, a: number) => void;
  onClear: (id: string) => void;
}) {
  const home = teamById(teams, match.homeTeamId);
  const away = teamById(teams, match.awayTeamId);
  const def = defaultScore(match);
  const ov = overrides[match.id];
  const homeVal = ov?.homeScore ?? def?.homeScore;
  const awayVal = ov?.awayScore ?? def?.awayScore;
  const homeChanged = ov != null;
  const isKO = match.stage !== "GROUP";

  const inputStyle = (changed: boolean): React.CSSProperties => ({
    width: 36,
    height: 28,
    textAlign: "center",
    fontFamily: "var(--font-mono)",
    fontSize: 14,
    fontWeight: 700,
    color: changed ? "var(--turf)" : "var(--ink)",
    background: "var(--bg-raised)",
    border: `1px solid ${changed ? "var(--turf)" : "var(--line)"}`,
    borderRadius: "var(--radius-sm)",
    outline: "none",
    MozAppearance: "textfield",
  });

  return (
    <div style={{
      display: "flex", alignItems: "center", gap: 10,
      padding: "6px 12px",
      background: "var(--bg-card)", border: "1px solid var(--line-soft)",
      borderRadius: "var(--radius-sm)",
      fontSize: 13,
    }}>
      <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-faint)", minWidth: 75 }}>
        {phaseLabel(match)}
      </span>
      <span style={{ display: "flex", alignItems: "center", gap: 6, minWidth: 0, flex: 1, justifyContent: "flex-end" }}>
        <Flag team={home} size={18} />
        <span style={{ fontWeight: 600, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: 140 }}>
          {home?.name ?? "—"}
        </span>
      </span>
      <input
        type="number"
        min={0}
        style={inputStyle(homeChanged)}
        value={homeVal ?? ""}
        placeholder="–"
        onChange={(e) => {
          const v = parseInt(e.target.value, 10);
          if (!isNaN(v) && v >= 0) {
            onScore(match.id, v, awayVal ?? (isKO ? 0 : 1));
          } else if (e.target.value === "") {
            // Bei Leerung: Standard wiederherstellen
            const fallback = def;
            if (fallback) onScore(match.id, fallback.homeScore, fallback.awayScore);
          }
        }}
      />
      <span style={{ fontFamily: "var(--font-mono)", fontWeight: 700, color: "var(--ink-faint)" }}>:</span>
      <input
        type="number"
        min={0}
        style={inputStyle(homeChanged)}
        value={awayVal ?? ""}
        placeholder="–"
        onChange={(e) => {
          const v = parseInt(e.target.value, 10);
          if (!isNaN(v) && v >= 0) {
            onScore(match.id, homeVal ?? (isKO ? 0 : 1), v);
          } else if (e.target.value === "") {
            const fallback = def;
            if (fallback) onScore(match.id, fallback.homeScore, fallback.awayScore);
            else onClear(match.id);
          }
        }}
      />
      <span style={{ display: "flex", alignItems: "center", gap: 6, minWidth: 0, flex: 1 }}>
        <span style={{ fontWeight: 600, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: 140 }}>
          {away?.name ?? "—"}
        </span>
        <Flag team={away} size={18} />
      </span>
      <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-faint)", minWidth: 100, textAlign: "right" }}>
        {fmtDate(match.utcDate)}
      </span>
    </div>
  );
}
