// /app/components/MatchDetails.tsx
'use client'

import { useState, useEffect, useMemo, useRef } from 'react'
import { useRouter } from 'next/navigation'
import { useSession } from 'next-auth/react'
import { format } from 'date-fns'
import { de } from 'date-fns/locale'

import Table from './Table'
import PremierRankBadge from './PremierRankBadge'
import CompRankBadge from './CompRankBadge'
import EditMatchMetaModal from './EditMatchMetaModal'
import EditMatchPlayersModal from './EditMatchPlayersModal'
import type { EditSide } from './EditMatchPlayersModal'

import type { Match, MatchPlayer } from '../types/match'
import Button from './Button'
import { MAP_OPTIONS } from '../lib/mapOptions'
import MapVoteBanner from './MapVoteBanner'
import { useSSEStore } from '@/app/lib/useSSEStore'
import { Team } from '../types/team'
import Alert from './Alert'
import Image from 'next/image'
import Link from 'next/link'

type TeamWithPlayers = Team & { players?: MatchPlayer[] }

/* ─────────────────── Hilfsfunktionen ────────────────────────── */
const kdr = (k?: number, d?: number) =>
  typeof k === 'number' && typeof d === 'number'
    ? d === 0
      ? '∞'
      : (k / d).toFixed(2)
    : '-'

const adr = (dmg?: number, rounds?: number) =>
  typeof dmg === 'number' && typeof rounds === 'number' && rounds > 0
    ? (dmg / rounds).toFixed(1)
    : '-'

const normalizeMapKey = (raw?: string) =>
  (raw ?? '').toLowerCase().replace(/\.bsp$/, '').replace(/^.*\//, '')

type VoteAction = 'BAN' | 'PICK' | 'DECIDER'
type VoteStep = { order: number; action: VoteAction; map?: string | null }

const mapLabelFromKey = (key?: string) => {
  const k = (key ?? '').toLowerCase().replace(/\.bsp$/,'').replace(/^.*\//,'')
  return (
    MAP_OPTIONS.find(o => o.key === k)?.label ?? (k ? k : 'TBD')
  )
}

// Maps aus dem MapVote (nur PICK/DECIDER, sortiert)
function extractSeriesMaps(match: Match): string[] {
  const steps = (match.mapVote?.steps ?? []) as unknown as VoteStep[]
  const picks = steps
    .filter(s => s && (s.action === 'PICK' || s.action === 'DECIDER'))
    .sort((a,b) => (a.order ?? 0) - (b.order ?? 0))
    .map(s => s.map ?? '')
  const n = Math.max(1, match.bestOf ?? 1)
  return picks.slice(0, n)
}

function SeriesStrip({
  bestOf,
  scoreA = 0,
  scoreB = 0,
  maps,
}: {
  bestOf: number
  scoreA?: number | null
  scoreB?: number | null
  maps: string[]
}) {
  const winsA = Math.max(0, scoreA ?? 0)
  const winsB = Math.max(0, scoreB ?? 0)
  const needed = Math.ceil(bestOf / 2)
  const total = Math.max(bestOf, maps.length || 1)

  const finished = winsA >= needed || winsB >= needed
  const currentIdx = finished ? -1 : Math.min(winsA + winsB, total - 1)

  return (
    <div className="w-full">
      <div className="flex items-center justify-between mb-2">
        <div className="text-sm text-gray-400">
          Best of {bestOf} • First to {needed}
        </div>
        <div className="text-sm font-semibold">
          {winsA}:{winsB}
        </div>
      </div>

      <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2">
        {Array.from({ length: total }).map((_, i) => {
          const key = maps[i] ?? ''
          const label = mapLabelFromKey(key)

          const isDone = i < winsA + winsB
          const isCurrent = i === currentIdx
          const isFuture = i > winsA + winsB

          return (
            <div
              key={`series-map-${i}`}
              className={[
                'rounded-md px-3 py-2 border flex items-center justify-between',
                isCurrent
                  ? 'border-blue-500 ring-2 ring-blue-300/50 bg-blue-500/10'
                  : isDone
                  ? 'border-emerald-500 bg-emerald-500/10'
                  : 'border-gray-600 bg-neutral-800/40',
              ].join(' ')}
            >
              <div className="flex items-center gap-2 min-w-0">
                <span className="text-xs opacity-70 shrink-0">Map {i + 1}</span>
                <span className="font-medium truncate">{label}</span>
              </div>

              <div className="flex items-center gap-1 shrink-0">
                {isDone && (
                  <span className="text-emerald-400 text-xs font-semibold">✔</span>
                )}
                {isCurrent && !isDone && !isFuture && (
                  <span className="text-blue-400 text-[11px] font-semibold">LIVE / als Nächstes</span>
                )}
              </div>
            </div>
          )
        })}
      </div>
    </div>
  )
}

/* ─────────────────── Komponente ─────────────────────────────── */
export function MatchDetails({ match, initialNow }: { match: Match; initialNow: number }) {
  const { data: session } = useSession()
  const { lastEvent } = useSSEStore()
  const router = useRouter()
  const isAdmin = !!session?.user?.isAdmin

  // Hydration-sicher: keine sich ändernden Werte im SSR rendern
  // Wir brauchen "now" nur, um zu entscheiden, ob Mapvote schon gestartet ist
  const [now, setNow] = useState(initialNow)
  const [editMetaOpen, setEditMetaOpen] = useState(false)

  // Lokale Overrides (analog MapVoteBanner), damit die Clients sofort reagieren
  const [opensAtOverride, setOpensAtOverride] = useState<number | null>(null)
  const [leadOverride, setLeadOverride] = useState<number | null>(null)
  const lastHandledKeyRef = useRef<string>('')

  /* ─── Rollen & Rechte ─────────────────────────────────────── */
  const me = session?.user
  const userId = me?.steamId
  const isLeaderA = !!userId && userId === match.teamA?.leader?.steamId
  const isLeaderB = !!userId && userId === match.teamB?.leader?.steamId
  const canEditA = isAdmin || isLeaderA
  const canEditB = isAdmin || isLeaderB

  const teamAPlayers = (match.teamA as TeamWithPlayers).players ?? []
  const teamBPlayers = (match.teamB as TeamWithPlayers).players ?? []

  /* ─── Map-Label ───────────────────────────────────────────── */
  const mapKey = normalizeMapKey(match.map)
  const mapLabel =
    MAP_OPTIONS.find(opt => opt.key === mapKey)?.label ??
    MAP_OPTIONS.find(opt => opt.key === 'lobby_mapvote')?.label ??
    'Unbekannte Map'

  /* ─── Match-Zeitpunkt (vom Server; ändert sich via router.refresh) ─── */
  const dateString = match.matchDate ?? match.demoDate
  const readableDate = dateString ? format(new Date(dateString), 'PPpp', { locale: de }) : 'Unbekannt'

  const seriesMaps = useMemo(() => {
    const fromVote = extractSeriesMaps(match)
    const n = Math.max(1, match.bestOf ?? 1)
    return fromVote.length >= n ? fromVote : [...fromVote, ...Array.from({ length: n - fromVote.length }, () => '')]
  }, [match.bestOf, match.mapVote?.steps?.length])

  /* ─── Modal-State ─────────────────────────────────────────── */
  const [editSide, setEditSide] = useState<EditSide | null>(null)

  /* ─── Live-Uhr für Mapvote-Startfenster ───────────────────── */
  useEffect(() => {
    const id = setInterval(() => setNow(Date.now()), 1000)
    return () => clearInterval(id)
  }, [])

  // Basiszeit des Matches (stabil; für Berechnung von opensAt-Fallback)
  const matchBaseTs = useMemo(() => {
    const raw = match.matchDate ?? match.demoDate ?? initialNow
    return new Date(raw).getTime()
  }, [match.matchDate, match.demoDate, initialNow])

  // Zeitpunkt, wann der Mapvote öffnet (Parent errechnet und an Banner gereicht)
  const voteOpensAtTs = useMemo(() => {
    if (opensAtOverride != null) return opensAtOverride
    if (match.mapVote?.opensAt) return new Date(match.mapVote.opensAt).getTime()
    const lead = (leadOverride != null)
      ? leadOverride
      : (Number.isFinite(match.mapVote?.leadMinutes ?? NaN) ? (match.mapVote!.leadMinutes as number) : 60)
    return matchBaseTs - lead * 60_000
  }, [opensAtOverride, match.mapVote?.opensAt, match.mapVote?.leadMinutes, matchBaseTs, leadOverride])

  const sseOpensAtTs   = voteOpensAtTs
  const sseLeadMinutes = leadOverride

  const endDate = new Date(voteOpensAtTs)
  const mapvoteStarted = (match.mapVote?.isOpen ?? false) || now >= voteOpensAtTs

  const showEditA = canEditA && !mapvoteStarted
  const showEditB = canEditB && !mapvoteStarted

  /* ─── SSE-Listener (nur map-vote-updated & Co.) ───────────── */
  useEffect(() => {
    if (!lastEvent) return

    // robustes Unwrap
    const outer = lastEvent as any
    const maybeInner = outer?.payload
    const base = (maybeInner && typeof maybeInner === 'object' && 'type' in maybeInner && 'payload' in maybeInner)
      ? maybeInner
      : outer

    const type = base?.type
    const evt  = base?.payload ?? base
    if (!evt?.matchId || evt.matchId !== match.id) return

    // Dedupe-Key
    const key = `${type}|${evt.matchId}|${evt.opensAt ?? ''}|${Number.isFinite(evt.leadMinutes) ? evt.leadMinutes : ''}`
    if (key === lastHandledKeyRef.current) {
      // identisches Event bereits verarbeitet → ignorieren
      return
    }
    lastHandledKeyRef.current = key

    // eigentliche Verarbeitung
    if (type === 'map-vote-updated') {
      if (evt?.opensAt) {
        const ts = new Date(evt.opensAt).getTime()
        setOpensAtOverride(ts)
      }
      if (Number.isFinite(evt?.leadMinutes)) {
        const lead = Number(evt.leadMinutes)
        setLeadOverride(lead)
        if (!evt?.opensAt) {
          const baseTs = new Date(match.matchDate ?? match.demoDate ?? initialNow).getTime()
          setOpensAtOverride(baseTs - lead * 60_000)
        }
      }
      // damit match.matchDate & Co. neu vom Server kommen
      router.refresh()
      return
    }

    const REFRESH_TYPES = new Set(['map-vote-reset', 'map-vote-locked', 'map-vote-unlocked', 'match-lineup-updated'])
    if (REFRESH_TYPES.has(type) && evt?.matchId === match.id) {
      router.refresh()
    }
  }, [lastEvent, match.id, router, match.matchDate, match.demoDate, initialNow])

  /* ─── Tabellen-Layout (fixe Breiten) ───────────────────────── */
  const ColGroup = () => (
    <colgroup>
      <col style={{ width: '24%' }} />
      <col style={{ width: '8%' }} />
      {Array.from({ length: 13 }).map((_, i) => (
        <col key={i} style={{ width: '5.666%' }} />
      ))}
    </colgroup>
  )

  /* ─── Match löschen ────────────────────────────────────────── */
  const handleDelete = async () => {
    if (!confirm('Match wirklich löschen? Das kann nicht rückgängig gemacht werden.')) return
    try {
      const res = await fetch(`/api/matches/${match.id}/delete`, { method: 'POST' })
      if (!res.ok) {
        const j = await res.json().catch(() => ({}))
        alert(j.message ?? 'Löschen fehlgeschlagen')
        return
      }
      router.push('/schedule')
    } catch (e) {
      console.error('[MatchDetails] delete failed', e)
      alert('Löschen fehlgeschlagen.')
    }
  }

  /* ─── Spieler-Tabelle (pure; keine Hooks hier drin!) ──────── */
  const renderTable = (players: MatchPlayer[]) => {
    const sorted = [...players].sort(
      (a, b) => (b.stats?.totalDamage ?? 0) - (a.stats?.totalDamage ?? 0),
    )

    return (
      <Table>
        <ColGroup />
        <Table.Head>
          <Table.Row>
            {[
              'Spieler', 'Rank', 'Aim', 'K', 'A', 'D',
              '1K', '2K', '3K', '4K', '5K',
              'K/D', 'ADR', 'HS%', 'Damage',
            ].map((h) => (
              <Table.Cell key={h} as="th">
                {h}
              </Table.Cell>
            ))}
          </Table.Row>
        </Table.Head>

        <Table.Body>
          {sorted.map((p) => (
            <Table.Row key={p.user.steamId}>
              <Table.Cell
                className="py-1 flex items-center gap-2"
                hoverable
                onClick={() => router.push(`/profile/${p.user.steamId}`)}
              >
                <img
                  src={p.user.avatar || '/assets/img/avatars/default_steam_avatar.jpg'}
                  alt={p.user.name}
                  className="w-8 h-8 rounded-full mr-3"
                />
                <div className="font-semibold text-base">{p.user.name ?? 'Unbekannt'}</div>
              </Table.Cell>

              <Table.Cell>
                <div className="flex items-center gap-[6px]">
                  {match.matchType === 'premier'
                    ? <PremierRankBadge rank={p.stats?.rankNew ?? 0} />
                    : <CompRankBadge rank={p.stats?.rankNew ?? 0} />}
                  {match.matchType === 'premier' && typeof p.stats?.rankChange === 'number' && (
                    <span
                      className={`text-sm ${
                        p.stats.rankChange > 0
                          ? 'text-green-500'
                          : p.stats.rankChange < 0
                          ? 'text-red-500'
                          : ''
                      }`}
                    >
                      {p.stats.rankChange > 0 ? '+' : ''}
                      {p.stats.rankChange}
                    </span>
                  )}
                </div>
              </Table.Cell>

              <Table.Cell>
                {Number.isFinite(Number(p.stats?.aim))
                  ? `${Number(p.stats?.aim).toFixed(0)} %`
                  : '-'}
              </Table.Cell>
              <Table.Cell>{p.stats?.kills ?? '-'}</Table.Cell>
              <Table.Cell>{p.stats?.assists ?? '-'}</Table.Cell>
              <Table.Cell>{p.stats?.deaths ?? '-'}</Table.Cell>
              <Table.Cell>{p.stats?.oneK ?? '-'}</Table.Cell>
              <Table.Cell>{p.stats?.twoK ?? '-'}</Table.Cell>
              <Table.Cell>{p.stats?.threeK ?? '-'}</Table.Cell>
              <Table.Cell>{p.stats?.fourK ?? '-'}</Table.Cell>
              <Table.Cell>{p.stats?.fiveK ?? '-'}</Table.Cell>
              <Table.Cell>{kdr(p.stats?.kills, p.stats?.deaths)}</Table.Cell>
              <Table.Cell>{adr(p.stats?.totalDamage, match.roundCount)}</Table.Cell>
              <Table.Cell>{((p.stats?.headshotPct ?? 0) * 100).toFixed(0)}%</Table.Cell>
              <Table.Cell>{p.stats?.totalDamage?.toFixed(0) ?? '-'}</Table.Cell>
            </Table.Row>
          ))}
        </Table.Body>
      </Table>
    )
  }

  /* ─── Render ─────────────────────────────────────────────── */
  return (
    <div className="space-y-6">
      {/* Kopfzeile: Zurück + Admin-Buttons */}
      <div className="flex items-center justify-between">
        <Link href="/schedule">
          <Button color="gray" variant="outline">
            ← Zurück
          </Button>
        </Link>

        {isAdmin && (
          <div className="flex gap-2">
            <Button
              onClick={() => setEditMetaOpen(true)}
              className="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1.5 rounded-md"
            >
              Match bearbeiten
            </Button>
            <Button
              onClick={handleDelete}
              className="bg-red-600 hover:bg-red-700 text-white px-3 py-1.5 rounded-md"
            >
              Match löschen
            </Button>
          </div>
        )}
      </div>

      <h1 className="text-2xl font-bold">
        Match auf {mapLabel} ({match.matchType})
      </h1>

      {/* Hydration-sicher: Datum kommt vom Server und ändert sich nach SSE via router.refresh() */}
      <p className="text-sm text-gray-500">Datum: {readableDate}</p>

      {(match.bestOf ?? 1) > 1 && (
        <div className="mt-3">
          <SeriesStrip
            bestOf={match.bestOf ?? 3}
            scoreA={match.scoreA}
            scoreB={match.scoreB}
            maps={extractSeriesMaps(match)}
          />
        </div>
      )}

      <div className="text-md mt-2">
        <strong>Teams:</strong> {match.teamA?.name ?? 'Unbekannt'} vs. {match.teamB?.name ?? 'Unbekannt'}
      </div>

      <div className="text-md">
        <strong>Score:</strong> {match.scoreA ?? 0}:{match.scoreB ?? 0}
      </div>

      {/* MapVote-Banner erhält die aktuell berechneten (SSE-konformen) Werte */}
      <MapVoteBanner
        match={match}
        initialNow={initialNow}
        matchBaseTs={matchBaseTs}
        sseOpensAtTs={sseOpensAtTs}
        sseLeadMinutes={sseLeadMinutes}
      />

      {/* ───────── Team-Blöcke ───────── */}
      <div className="border-t pt-4 mt-4 space-y-10">
        {/* Team A */}
        <div>
          <div className="flex items-center justify-between mb-2">
            <h2 className="text-xl font-semibold">{match.teamA?.name ?? 'Team A'}</h2>

            <Alert type="soft" color="dark" className="flex items-center justify-between gap-4">
              <div className="flex items-center gap-2">
                {canEditA && !mapvoteStarted ? (
                  <svg xmlns="http://www.w3.org/2000/svg" fill="green" height="20" width="20" viewBox="0 0 640 640">
                    <path d="M416 160C416 124.7 444.7 96 480 96C515.3 96 544 124.7 544 160L544 192C544 209.7 558.3 224 576 224C593.7 224 608 209.7 608 192L608 160C608 89.3 550.7 32 480 32C409.3 32 352 89.3 352 160L352 224L192 224C156.7 224 128 252.7 128 288L128 512C128 547.3 156.7 576 192 576L448 576C483.3 576 512 547.3 512 512L512 288C512 252.7 483.3 224 448 224L416 224L416 160z"/>
                  </svg>
                ) : (
                  <svg xmlns="http://www.w3.org/2000/svg" fill="red" height="20" width="20" viewBox="0 0 640 640">
                    <path d="M256 160L256 224L384 224L384 160C384 124.7 355.3 96 320 96C284.7 96 256 124.7 256 160zM192 224L192 160C192 89.3 249.3 32 320 32C390.7 32 448 89.3 448 160L448 224C483.3 224 512 252.7 512 288L512 512C512 547.3 483.3 576 448 576L192 576C156.7 576 128 547.3 128 512L128 288C128 252.7 156.7 224 192 224z"/>
                  </svg>
                )}

                <span className='text-gray-300'>
                  {canEditA && !mapvoteStarted ? (
                    <>
                      Du kannst die Aufstellung noch bis{' '}
                      <strong>{format(endDate, 'dd.MM.yyyy HH:mm')}</strong> bearbeiten.
                    </>
                  ) : (
                    <>Die Aufstellung kann nicht mehr bearbeitet werden.</>
                  )}
                </span>
              </div>

              <Button
                size="sm"
                onClick={() => (canEditA && !mapvoteStarted) && setEditSide('A')}
                disabled={!(canEditA && !mapvoteStarted)}
                className={`px-3 py-1.5 text-sm rounded-lg ${
                  canEditA && !mapvoteStarted
                    ? 'bg-blue-600 hover:bg-blue-700 text-white'
                    : 'bg-gray-400 text-gray-200 cursor-not-allowed'
                }`}
              >
                Spieler bearbeiten
              </Button>
            </Alert>
          </div>

          {renderTable(teamAPlayers)}
        </div>

        {/* Team B */}
        <div>
          <div className="flex items-center justify-between mb-2">
            <h2 className="text-xl font-semibold">
              {match.teamB?.logo && (
                <span className="relative inline-block w-8 h-8 mr-2 align-middle">
                  <Image
                    src={match.teamB.logo ? `/assets/img/logos/${match.teamB.logo}` : `/assets/img/logos/cs2.webp`}
                    alt="Teamlogo"
                    fill
                    sizes="64px"
                    quality={75}
                    priority={false}
                  />
                </span>
              )}
              {match.teamB?.name ?? 'Team B'}
            </h2>

            <Alert type="soft" color="dark" className="flex items-center justify-between gap-4">
              <div className="flex items-center gap-2">
                {canEditB && !mapvoteStarted ? (
                  <svg xmlns="http://www.w3.org/2000/svg" fill="green" height="20" width="20" viewBox="0 0 640 640">
                    <path d="M416 160C416 124.7 444.7 96 480 96C515.3 96 544 124.7 544 160L544 192C544 209.7 558.3 224 576 224C593.7 224 608 209.7 608 192L608 160C608 89.3 550.7 32 480 32C409.3 32 352 89.3 352 160L352 224L192 224C156.7 224 128 252.7 128 288L128 512C128 547.3 156.7 576 192 576L448 576C483.3 576 512 547.3 512 512L512 288C512 252.7 483.3 224 448 224L416 224L416 160z"/>
                  </svg>
                ) : (
                  <svg xmlns="http://www.w3.org/2000/svg" fill="red" height="20" width="20" viewBox="0 0 640 640">
                    <path d="M256 160L256 224L384 224L384 160C384 124.7 355.3 96 320 96C284.7 96 256 124.7 256 160zM192 224L192 160C192 89.3 249.3 32 320 32C390.7 32 448 89.3 448 160L448 224C483.3 224 512 252.7 512 288L512 512C512 547.3 483.3 576 448 576L192 576C156.7 576 128 547.3 128 512L128 288C128 252.7 156.7 224 192 224z"/>
                  </svg>
                )}

                <span className='text-gray-300'>
                  {canEditB && !mapvoteStarted ? (
                    <>
                      Du kannst die Aufstellung noch bis{' '}
                      <strong>{format(endDate, 'dd.MM.yyyy HH:mm')}</strong> bearbeiten.
                    </>
                  ) : (
                    <>Die Aufstellung kann nicht mehr bearbeitet werden.</>
                  )}
                </span>
              </div>

              <Button
                size="sm"
                onClick={() => (canEditB && !mapvoteStarted) && setEditSide('B')}
                disabled={!(canEditB && !mapvoteStarted)}
                className={`px-3 py-1.5 text-sm rounded-lg ${
                  canEditB && !mapvoteStarted
                    ? 'bg-blue-600 hover:bg-blue-700 text-white'
                    : 'bg-gray-400 text-gray-200 cursor-not-allowed'
                }`}
              >
                Spieler bearbeiten
              </Button>
            </Alert>
          </div>

          {renderTable(teamBPlayers)}
        </div>
      </div>

      {/* ───────── Modal ───────── */}
      {editSide && (
        <EditMatchPlayersModal
          show
          onClose={() => setEditSide(null)}
          matchId={match.id}
          teamA={match.teamA}
          teamB={match.teamB}
          side={editSide}
          initialA={teamAPlayers.map((mp) => mp.user.steamId)}
          initialB={teamBPlayers.map((mp) => mp.user.steamId)}
          onSaved={() => router.refresh()}
        />
      )}

      {editMetaOpen && (
        <EditMatchMetaModal
          show
          onClose={() => setEditMetaOpen(false)}
          matchId={match.id}
          defaultTitle={match.title}
          defaultTeamAId={match.teamA?.id ?? null}
          defaultTeamBId={match.teamB?.id ?? null}
          defaultTeamAName={match.teamA?.name ?? null}
          defaultTeamBName={match.teamB?.name ?? null}
          defaultDateISO={match.matchDate ?? match.demoDate ?? null}
          defaultMap={match.map ?? null}
          defaultVoteLeadMinutes={match.mapVote?.leadMinutes ?? 60}
          onSaved={() => { setTimeout(() => router.refresh(), 0) }}
        />
      )}
    </div>
  )
}
