// CommunityMatchList.tsx

'use client'

import { useEffect, useState, useCallback, useMemo } from 'react'
import { useSession } from 'next-auth/react'
import { useTranslations, useLocale } from 'next-intl'
import Link from 'next/link'
import Image from 'next/image'
import Switch from '../components/Switch'
import Button from './Button'
import Modal from './Modal'
import { Match } from '../../../types/match'
import { useSSEStore } from '@/lib/useSSEStore'
import { useUserTimeZone } from '@/hooks/useUserTimeZone'

type Props = { matchType?: string }

const getTeamLogo = (logo?: string | null) =>
  logo ? `/assets/img/logos/${logo}` : '/assets/img/logos/cs2.webp'

type TeamOption = { id: string; name: string; logo?: string | null }

type UnknownRec = Record<string, unknown>;

function isRecord(v: unknown): v is UnknownRec {
  return !!v && typeof v === 'object';
}

type PlayerLike = {
  user?: { steamId?: string | null } | null;
  steamId?: string | null;
};

type TeamMaybeWithPlayers = {
  id?: string | null;
  players?: PlayerLike[] | null;
};

function toStringOrNull(v: unknown): string | null {
  return typeof v === 'string' ? v : null;
}

function firstString(...vals: unknown[]): string {
  for (const v of vals) if (typeof v === 'string') return v;
  return '';
}

/** lokale Date+Time -> ISO (bewahrt lokale Uhrzeit) */
function combineLocalDateTime(dateStr: string, timeStr: string) {
  const [y, m, d] = dateStr.split('-').map(Number)
  const [hh, mm]  = timeStr.split(':').map(Number)
  const dt = new Date(y, (m - 1), d, hh, mm, 0, 0) // lokale Zeit
  return dt.toISOString()
}

/** nächste volle Stunde als Default */
function getNextHourDefaults() {
  const now = new Date()
  now.setMinutes(0, 0, 0)
  now.setHours(now.getHours() + 1)
  const dateStr = now.toISOString().slice(0, 10)
  const timeStr = now.toTimeString().slice(0, 5) // HH:MM
  return { dateStr, timeStr }
}

// 👇 Helper für Map-Vote-Status
function getMapVoteState(m: Match, nowMs: number) {
  const opensAt = m?.mapVote?.opensAt ? new Date(m.mapVote.opensAt) : null
  const locked  = m?.mapVote?.locked ?? false
  if (!opensAt) return { hasVote: false as const }

  const opensAtMs = opensAt.getTime()
  const isOpen    = !locked && opensAtMs <= nowMs
  const opensInMs = Math.max(0, opensAtMs - nowMs) // nie negativ

  return { hasVote: true as const, isOpen, opensAt, opensInMs }
}

// ---- Timezone Utils ----
type ZonedParts = {
  year: number; month: number; day: number; hour: number; minute: number;
};

function getZonedParts(date: Date | string, timeZone: string, locale = 'de-DE'): ZonedParts {
  const d = typeof date === 'string' ? new Date(date) : date;
  const parts = new Intl.DateTimeFormat(locale, {
    timeZone,
    year: 'numeric', month: '2-digit', day: '2-digit',
    hour: '2-digit', minute: '2-digit', hour12: false,
  }).formatToParts(d);

  const g = (t: string) => Number(parts.find(p => p.type === t)?.value ?? '0');
  return { year: g('year'), month: g('month'), day: g('day'), hour: g('hour'), minute: g('minute') };
}

function formatDateInTZ(date: Date | string, timeZone: string, locale = 'de-DE') {
  const p = getZonedParts(date, timeZone, locale);
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${pad(p.day)}.${pad(p.month)}.${p.year}`;
}

function formatTimeInTZ(date: Date | string, timeZone: string, locale = 'de-DE') {
  const p = getZonedParts(date, timeZone, locale);
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${pad(p.hour)}:${pad(p.minute)}`;
}

function dateKeyInTZ(date: Date | string, timeZone: string): string {
  const p = getZonedParts(date, timeZone);
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${p.year}-${pad(p.month)}-${pad(p.day)}`; // YYYY-MM-DD
}

type BanStatus = {
  vacBanned?: boolean | null
  numberOfVACBans?: number | null
  numberOfGameBans?: number | null
  communityBanned?: boolean | null
  economyBan?: string | null
  daysSinceLastBan?: number | null
}

function isBanStatusFlagged(b?: BanStatus | null): boolean {
  if (!b) return false
  const econ = (b.economyBan ?? 'none').toLowerCase()
  const hasEcon = econ !== 'none' && econ !== ''
  return (
    b.vacBanned === true ||
    (b.numberOfVACBans ?? 0) > 0 ||
    (b.numberOfGameBans ?? 0) > 0 ||
    b.communityBanned === true ||
    hasEcon
  )
}

/** Liefert Info, ob Match gebannte Spieler enthält (zählt beide Seiten) */
function matchBanInfo(m: Match): { hasBan: boolean; count: number; tooltip: string } {
  const teamA = (m.teamA as unknown as TeamMaybeWithPlayers);
  const teamB = (m.teamB as unknown as TeamMaybeWithPlayers);

  const playersA = Array.isArray(teamA?.players) ? teamA.players! : [];
  const playersB = Array.isArray(teamB?.players) ? teamB.players! : [];

  // Fallback: flaches players-Array (ältere API)
  const flat = (m as unknown as { players?: PlayerLike[] | null }).players ?? [];

  const all: PlayerLike[] =
    playersA.length || playersB.length ? [...playersA, ...playersB] : Array.isArray(flat) ? flat : [];

  let count = 0;
  const lines: string[] = [];
  for (const p of all) {
    const user = (p?.user as unknown as { name?: string | null; banStatus?: BanStatus | null }) ?? {};
    const name = user?.name ?? 'Unbekannt';
    const b = user?.banStatus ?? null;
    if (isBanStatusFlagged(b)) {
      count++;
      const parts: string[] = [];
      if (b?.vacBanned) parts.push('VAC aktiv');
      if ((b?.numberOfVACBans ?? 0) > 0) parts.push(`VAC=${b?.numberOfVACBans}`);
      if ((b?.numberOfGameBans ?? 0) > 0) parts.push(`Game=${b?.numberOfGameBans}`);
      if (b?.communityBanned) parts.push('Community');
      if (b?.economyBan && b.economyBan !== 'none') parts.push(`Economy=${b.economyBan}`);
      if (typeof b?.daysSinceLastBan === 'number') parts.push(`Tage seit Ban=${b.daysSinceLastBan}`);
      lines.push(`${name}: ${parts.join(' · ')}`);
    }
  }

  return { hasBan: count > 0, count, tooltip: lines.join('\n') };
}

export default function CommunityMatchList({ matchType }: Props) {
  const { data: session } = useSession()
  const locale = useLocale()
  const userTZ = useUserTimeZone([session?.user?.steamId])
  const weekdayFmt = useMemo(() =>
    new Intl.DateTimeFormat(locale === 'de' ? 'de-DE' : 'en-GB', {
      weekday: 'long',
      timeZone: userTZ,
    }),
  [locale, userTZ])
  
  const tMatches = useTranslations('matches')
  const tMapvote = useTranslations('mapvote')

  const { lastEvent }     = useSSEStore()

  const [matches, setMatches] = useState<Match[]>([])
  const [onlyOwn, setOnlyOwn] = useState(false)

  // Modal-States
  const [showCreate, setShowCreate] = useState(false)
  const [teams, setTeams] = useState<TeamOption[]>([])
  const [loadingTeams, setLoadingTeams] = useState(false)
  const [saving, setSaving] = useState(false)

  const [teamAId, setTeamAId] = useState<string>('')
  const [teamBId, setTeamBId] = useState<string>('')
  const [title, setTitle] = useState<string>('')        // auto editierbar
  const [autoTitle, setAutoTitle] = useState(true)
  const [bestOf, setBestOf] = useState<3 | 5>(3)

  // Datum & Uhrzeit
  const defaults = getNextHourDefaults()
  const [matchDateStr, setMatchDateStr] = useState<string>(defaults.dateStr) // YYYY-MM-DD
  const [matchTimeStr, setMatchTimeStr] = useState<string>(defaults.timeStr) // HH:MM
  
  const pad = (n: number) => String(n).padStart(2, '0');
  const hours = Array.from({ length: 24 }, (_, i) => i);
  const quarters = [0, 15, 30, 45];

  const teamById = useCallback(
    (id?: string) => teams.find(t => t.id === id),
    [teams]
  )

  const [now, setNow] = useState(() => Date.now())

  const mySteamId = session?.user?.steamId

  const isOwnMatch = useCallback((m: Match) => {
    if (!mySteamId) return false;

    const teamA = (m.teamA as unknown as TeamMaybeWithPlayers);
    const teamB = (m.teamB as unknown as TeamMaybeWithPlayers);

    const inTeamA =
      Array.isArray(teamA?.players) &&
      teamA.players!.some((p) => p?.user?.steamId === mySteamId || p?.steamId === mySteamId);

    const inTeamB =
      Array.isArray(teamB?.players) &&
      teamB.players!.some((p) => p?.user?.steamId === mySteamId || p?.steamId === mySteamId);

    if (inTeamA || inTeamB) return true;

    // Fallback: flaches players-Array
    const flatPlayers = (m as unknown as { players?: PlayerLike[] | null }).players ?? [];
    const inFlat =
      Array.isArray(flatPlayers) &&
      flatPlayers.some((p) => p?.user?.steamId === mySteamId || p?.steamId === mySteamId);

    if (inFlat) return true;

    // Optionaler Fallback: Team-Mitgliedschaft
    const byTeamMembership =
      !!session?.user?.team && (m?.teamA?.id === session.user.team || m?.teamB?.id === session.user.team);

    return byTeamMembership;
  }, [mySteamId, session?.user?.team]);

  useEffect(() => {
    const id = setInterval(() => setNow(Date.now()), 1000)
    return () => clearInterval(id)
  }, [])

  useEffect(() => {
    const id = setInterval(() => {
      // force re-render, damit isOpen (Vergleich mit Date.now) neu bewertet wird
      setMatches(m => [...m])
    }, 30_000)
    return () => clearInterval(id)
  }, [])


  // Auto-Titel
  useEffect(() => {
    if (!autoTitle) return
    const a = teamById(teamAId)?.name ?? 'Team A'
    const b = teamById(teamBId)?.name ?? 'Team B'
    setTitle(`${a} vs ${b}`)
  }, [teamAId, teamBId, autoTitle, teamById])

  // Matches laden
  const loadMatches = useCallback(async () => {
    const url = `/api/matches${matchType ? `?type=${encodeURIComponent(matchType)}` : ''}`
    try {
      const r = await fetch(url, { cache: 'no-store' })
      const data = r.ok ? await r.json() : []
      setMatches(data)
    } catch (err) {
      console.error('[MatchList] Laden fehlgeschlagen:', err)
    }
  }, [matchType])

  useEffect(() => { loadMatches() }, [loadMatches])
  

  useEffect(() => {
    if (!lastEvent) return

    // auf diese Typen reagieren
    const TRIGGER_TYPES = new Set([
      'match-created',
      'matches-updated',
      'match-deleted',
      'map-vote-updated', // damit das Map-Vote Badge live aktualisiert
    ])

    if (!TRIGGER_TYPES.has(lastEvent.type)) return

    // kurzer Cooldown, falls mehrere Events gleichzeitig eintreffen
    let cancelled = false
    const t = setTimeout(async () => {
      if (!cancelled) await loadMatches()
    }, 150)
    return () => { cancelled = true; clearTimeout(t) }
  }, [lastEvent, loadMatches])

  // Teams laden, wenn Modal aufgeht (robust gegen verschiedene Response-Shapes)
  useEffect(() => {
    if (!showCreate) return

    let ignore = false
    const ctrl = new AbortController()

    ;(async () => {
      setLoadingTeams(true)
      try {
        const res  = await fetch('/api/teams', {
          cache: 'no-store',
          credentials: 'same-origin',   // wichtig: Cookies mitnehmen
          signal: ctrl.signal,
        })
        const json: unknown = await res.json().catch(() => ({}));
        const raw: unknown =
          (isRecord(json) && Array.isArray(json.teams)) ? json.teams :
          (isRecord(json) && Array.isArray(json.data))  ? json.data  :
          (isRecord(json) && Array.isArray(json.items)) ? json.items :
          Array.isArray(json) ? json : [];

        const arr: UnknownRec[] = Array.isArray(raw) ? (raw as UnknownRec[]) : [];

        const opts: TeamOption[] = arr
          .map((r) => {
            const id = firstString(r.id, r._id, r.teamId, r.uuid);
            const name = firstString(r.name, r.title, r.displayName, r.tag) || 'Unbenanntes Team';
            const logo = toStringOrNull(r.logo ?? r.logoUrl ?? r.image) ?? null;
            return { id, name, logo };
          })
          .filter((t) => !!t.id && !!t.name);

        if (!ignore) setTeams(opts)
      } catch (e) {
        if (!ignore) {
          console.error('[MatchList] /api/teams fehlgeschlagen:', e)
          setTeams([])
        }
      } finally {
        if (!ignore) setLoadingTeams(false)
      }
    })()

    return () => { ignore = true; ctrl.abort() }
  }, [showCreate])

  useEffect(() => {
    if (!showCreate) return
    if (teams.length >= 2 && !teamAId && !teamBId) {
      setTeamAId(teams[0].id)
      setTeamBId(teams[1].id)
    }
  }, [teams, showCreate, teamAId, teamBId])

  const resetCreateState = () => {
    setTeamAId('')
    setTeamBId('')
    setTitle('')
    setAutoTitle(true)
    setBestOf(3)
    const d = getNextHourDefaults()
    setMatchDateStr(d.dateStr)
    setMatchTimeStr(d.timeStr)
  }

  const canSave =
    !saving &&
    teamAId &&
    teamBId &&
    teamAId !== teamBId &&
    title.trim().length > 0 &&
    (bestOf === 3 || bestOf === 5) &&
    !!matchDateStr &&
    !!matchTimeStr

  const handleCreate = async () => {
    if (!canSave) return
    setSaving(true)
    try {
      const matchDateISO = combineLocalDateTime(matchDateStr, matchTimeStr)
      const res = await fetch('/api/matches/create', {
        method : 'POST',
        headers: { 'Content-Type': 'application/json' },
        body   : JSON.stringify({
          teamAId,
          teamBId,
          title: title.trim(),
          bestOf,                  // 3 | 5
          matchDate: matchDateISO, // <- Datum+Zeit
          type : matchType,        // optional
        }),
      })
      if (!res.ok) {
        const j = await res.json().catch(() => ({}))
        alert(j.message ?? 'Erstellen fehlgeschlagen')
        return
      }
      setShowCreate(false)
      resetCreateState()
      await loadMatches()
    } catch (e) {
      console.error('[MatchList] Match erstellen fehlgeschlagen:', e)
      alert('Match konnte nicht erstellt werden.')
    } finally {
      setSaving(false)
    }
  }

  // Gruppieren
  const grouped = useMemo(() => {
    // optional filtern
    const base = onlyOwn ? matches.filter(isOwnMatch) : matches

    const sorted = [...base].sort(
      (a, b) => new Date(a.demoDate).getTime() - new Date(b.demoDate).getTime(),
    )
    const map = new Map<string, Match[]>()
    for (const m of sorted) {
      const key = dateKeyInTZ(m.demoDate, userTZ)
      map.set(key, [...(map.get(key) ?? []), m])
    }
    return Array.from(map.entries())
  }, [matches, onlyOwn, isOwnMatch, userTZ])

  return (
    <div className="max-w-7xl mx-auto py-8 px-4 space-y-6">
      {/* Kopfzeile */}
      <div className="flex items-center justify-between flex-wrap gap-y-4">
        <h1 className="text-2xl font-bold text-gray-700 dark:text-neutral-300">
          {tMatches("title")}
        </h1>
        <div className="flex items-center gap-4">
          <Switch
            id="only-own-team"
            checked={onlyOwn}
            onChange={setOnlyOwn}
            labelRight={tMatches("filter")}
          />
          {session?.user?.isAdmin && (
            <Button color="blue" onClick={() => setShowCreate(true)}>
              {tMatches("create-match")}
            </Button>
          )}
        </div>
      </div>

      {/* Inhalt */}
      {grouped.length === 0 ? (
        <p className="text-gray-700 dark:text-neutral-300">{tMatches("description")}</p>
      ) : (
        <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
          {grouped.map(([dateKey, dayMatches], dayIdx) => {
            const dateObj  = new Date(dateKey + 'T00:00:00');
            const weekday  = weekdayFmt.format(dateObj);
            const dayLabel = `${tMatches('day')} #${dayIdx + 1} – ${weekday}`;
            return (
              <div key={dateKey} className="flex flex-col gap-4">
                <div className="bg-yellow-300 dark:bg-yellow-500 text-center py-2 font-bold tracking-wider">
                  {dayLabel}<br />{dateKey}
                </div>
                {dayMatches.map((m: Match) => {
                  const started    = new Date(m.demoDate).getTime() <= Date.now()
                  const unfinished = !m.winnerTeam && m.scoreA == null && m.scoreB == null
                  const isLive     = started && unfinished
                  const isOwn = isOwnMatch(m)
                  const dimmed = onlyOwn ? false : !isOwn
                  const banInfo = matchBanInfo(m)

                  // 👇 Map-Vote Status berechnen
                  const mv = getMapVoteState(m, now)
                  const opensText =
                    mv.hasVote && !mv.isOpen && mv.opensAt
                      ? `${tMapvote("opens-in")} ${formatCountdown(mv.opensInMs)}`
                      : null

                  return (
                    <Link
                      key={m.id}
                      href={`/match-details/${m.id}`}
                      className={`
                        grid grid-rows-[auto_1fr_auto] justify-items-center gap-3
                        bg-neutral-300 dark:bg-neutral-800 text-gray-800 dark:text-white
                        rounded-sm p-4 min-h-[210px]
                        hover:scale-105 hover:bg-neutral-400 hover:dark:bg-neutral-700 hover:shadow-md
                        transition-transform transition-opacity duration-300 ease-in-out
                        ${dimmed ? 'opacity-40' : 'opacity-100'}
                        ${banInfo.hasBan ? 'ring-2 ring-red-500/70 bg-red-900/10' : ''}
                      `}
                    >
                      {/* Zeile 1: Badges (immer Platz, auch wenn leer) */}
                      <div className="flex flex-col items-center gap-1 min-h-6">
                        {isLive ? (
                          <span className="px-2 py-0.5 text-xs font-semibold rounded-full bg-red-500 text-white shadow">
                            LIVE
                          </span>
                        ) : mv.hasVote && (mv.isOpen || opensText) ? (
                          <>
                            {mv.isOpen && (
                              <span className="px-2 py-0.5 text-[11px] font-semibold rounded-full bg-green-600 text-white shadow">
                                Map-Vote offen
                              </span>
                            )}
                            {!mv.isOpen && opensText && (
                              <span
                                title={mv.opensAt?.toLocaleString('de-DE') ?? undefined}
                                className="px-2 py-0.5 text-[11px] font-medium rounded-full bg-yellow-300 text-gray-900 dark:bg-yellow-500 dark:text-black shadow"
                              >
                                Map-Vote {opensText}
                              </span>
                            )}
                          </>
                        ) : null}
                      </div>

                      {/* Zeile 2: Teams */}
                      <div className="flex w-full justify-around items-center">
                        <div className="flex flex-col items-center w-1/3">
                          <Image
                            src={getTeamLogo(m.teamA.logo)}
                            alt={m.teamA?.name ?? 'Team A'}
                            width={56}
                            height={56}
                            className="rounded-full border bg-white"
                          />
                          <span className="mt-2 text-xs text-center line-clamp-1">{m.teamA.name}</span>
                        </div>
                        <span className="font-bold">vs</span>
                        <div className="flex flex-col items-center w-1/3">
                          <Image
                            src={getTeamLogo(m.teamB.logo)}
                            alt={m.teamB?.name ?? 'Team B'}
                            width={56}
                            height={56}
                            className="rounded-full border bg-white"
                          />
                          <span className="mt-2 text-xs text-center line-clamp-1">{m.teamB.name}</span>
                        </div>
                      </div>

                      {/* Zeile 3: Datum & Uhrzeit */}
                      <div className="flex flex-col items-center -mt-1 space-y-1">
                        {/* Datum-Badge */}
                        <span
                          className={`px-3 py-1 rounded-full text-[13px] font-bold shadow ring-1 ring-black/10
                            ${isLive ? 'bg-red-500 text-white' : 'bg-yellow-400 text-gray-900 dark:bg-yellow-500 dark:text-black'}
                          `}
                        >
                          {formatDateInTZ(m.demoDate, userTZ, locale === 'de' ? 'de-DE' : 'en-GB')}
                        </span>

                        <span className="flex items-center gap-1 text-xs font-semibold opacity-90">
                          <svg xmlns="http://www.w3.org/2000/svg" className="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 512 512">
                            <path d="M256 48a208 208 0 1 0 208 208A208.24 208.24 0 0 0 256 48Zm0 384a176 176 0 1 1 176-176 176.2 176.2 0 0 1-176 176Zm80-176h-64V144a16 16 0 0 0-32 0v120a16 16 0 0 0 16 16h80a16 16 0 0 0 0-32Z" />
                          </svg>
                          {formatTimeInTZ(m.demoDate, userTZ, locale === 'de' ? 'de-DE' : 'en-GB')} Uhr
                        </span>
                      </div>
                    </Link>
                  )
                })}
              </div>
            )
          })}
        </div>
      )}

      {/* Modal: Match erstellen */}
      <Modal
        id="create-match-modal"
        title="Match erstellen"
        show={showCreate}
        onClose={() => { setShowCreate(false); resetCreateState() }}
        onSave={handleCreate}
        closeButtonTitle={saving ? 'Speichern …' : 'Erstellen'}
        closeButtonColor="blue"
      >
        <div className="space-y-4">
          {/* Team A */}
          <label className="block text-sm font-medium mb-1">Team A</label>
          <select
            className="w-full rounded-lg border border-gray-300 dark:border-neutral-700 bg-white dark:bg-neutral-800 px-3 py-2 text-sm"
            value={teamAId}
            onChange={(e) => setTeamAId(e.target.value)}
            disabled={loadingTeams}
          >
            <option value="">— bitte wählen —</option>
            {teams.map(t => <option key={t.id} value={t.id}>{t.name}</option>)}
          </select>

          {/* Team B */}
          <label className="block text-sm font-medium mb-1 mt-2">Team B</label>
          <select
            className="w-full rounded-lg border border-gray-300 dark:border-neutral-700 bg-white dark:bg-neutral-800 px-3 py-2 text-sm"
            value={teamBId}
            onChange={(e) => setTeamBId(e.target.value)}
            disabled={loadingTeams}
          >
            <option value="">— bitte wählen —</option>
            {teams.map(t => (
              <option key={t.id} value={t.id} disabled={t.id === teamAId}>
                {t.name}
              </option>
            ))}
          </select>

          {/* Titel */}
          <div className="mt-3">
            <label className="block text-sm font-medium mb-1">
              Titel {autoTitle && <span className="ml-2 text-xs text-gray-500">(automatisch)</span>}
            </label>
            <input
              type="text"
              value={title}
              onChange={(e) => { setTitle(e.target.value); setAutoTitle(false) }}
              onFocus={() => setAutoTitle(false)}
              className="w-full rounded-lg border border-gray-300 dark:border-neutral-700 bg-white dark:bg-neutral-800 px-3 py-2 text-sm"
              placeholder="Team A vs Team B"
            />
            {!autoTitle && (
              <button
                type="button"
                className="mt-1 text-xs text-blue-600 hover:underline"
                onClick={() => setAutoTitle(true)}
              >
                Titel wieder automatisch generieren
              </button>
            )}
          </div>

          {/* Datum & Uhrzeit */}
          <div className="mt-3">
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 items-end">
              {/* Links: Datum */}
              <div>
                <label className="block text-sm font-medium mb-1">Datum</label>
                <input
                  type="date"
                  value={matchDateStr}
                  min={new Date().toISOString().slice(0, 10)}
                  onChange={(e) => setMatchDateStr(e.target.value)}
                  className="w-full rounded-lg border border-gray-300 dark:border-neutral-700 bg-white dark:bg-neutral-800 px-3 py-2 text-sm"
                />
              </div>

              {/* Rechts: Uhrzeit (HH + MM in Vierteln) */}
              <div>
                <label className="block text-sm font-medium mb-1">Uhrzeit</label>
                <div className="flex gap-2">
                  {/* Stunde */}
                  <select
                    value={matchTimeStr.split(':')[0]}
                    onChange={(e) => {
                      const [, mm] = matchTimeStr.split(':');
                      setMatchTimeStr(`${pad(Number(e.target.value))}:${mm}`);
                    }}
                    className="w-full rounded-lg border border-gray-300 dark:border-neutral-700 bg-white dark:bg-neutral-800 px-3 py-2 text-sm"
                  >
                    {hours.map(h => <option key={h} value={pad(h)}>{pad(h)}</option>)}
                  </select>

                  {/* Minuten (00/15/30/45) */}
                  <select
                    value={pad(Math.round(Number(matchTimeStr.split(':')[1]) / 15) * 15 % 60)}
                    onChange={(e) => {
                      const [hh] = matchTimeStr.split(':');
                      setMatchTimeStr(`${hh}:${pad(Number(e.target.value))}`);
                    }}
                    className="w-full rounded-lg border border-gray-300 dark:border-neutral-700 bg-white dark:bg-neutral-800 px-3 py-2 text-sm"
                  >
                    {quarters.map(q => <option key={q} value={pad(q)}>{pad(q)}</option>)}
                  </select>
                </div>
              </div>
            </div>

            <p className="text-[11px] text-gray-500 dark:text-neutral-400 mt-1">
              Datum &amp; Uhrzeit werden als lokale Zeit gespeichert.
            </p>
          </div>

          {/* Best-of */}
          <div className="mt-3">
            <label className="block text-sm font-medium mb-1">Modus</label>
            <div className="flex gap-2">
              <button
                type="button"
                onClick={() => setBestOf(3)}
                className={`px-3 py-1.5 rounded-lg text-sm border ${bestOf === 3 ? 'bg-blue-600 text-white border-blue-600' : 'bg-transparent border-gray-300 dark:border-neutral-700 text-gray-800 dark:text-neutral-200'}`}
              >
                BO3
              </button>
              <button
                type="button"
                onClick={() => setBestOf(5)}
                className={`px-3 py-1.5 rounded-lg text-sm border ${bestOf === 5 ? 'bg-blue-600 text-white border-blue-600' : 'bg-transparent border-gray-300 dark:border-neutral-700 text-gray-800 dark:text-neutral-200'}`}
              >
                BO5
              </button>
            </div>
          </div>

          {loadingTeams && (
            <p className="text-sm text-gray-500 mt-2">Teams werden geladen …</p>
          )}
          {teamAId && teamBId && teamAId === teamBId && (
            <p className="text-sm text-red-600 mt-2">Bitte zwei unterschiedliche Teams wählen.</p>
          )}

          {!loadingTeams && showCreate && teams.length === 0 && (
            <p className="text-sm text-amber-600">
              Keine Teams gefunden. Prüfe den /api/teams Response (erwartet id & name).
            </p>
          )}
        </div>
      </Modal>
    </div>
  )
}

function formatCountdown(ms: number) {
  if (ms <= 0) return '0:00:00'
  const totalSec = Math.floor(ms / 1000)
  const h = Math.floor(totalSec / 3600)
  const m = Math.floor((totalSec % 3600) / 60)
  const s = totalSec % 60
  const pad = (n:number)=>String(n).padStart(2,'0')
  return `${h}:${pad(m)}:${pad(s)}`
}
