import { NextResponse } from "next/server"; import { fetchMatchesAndTeams, fetchOdds, attachOdds, fetchLiveScores, applyLiveScores, assignKONumbersBySlots } from "@/lib/feeds"; import { computeGroupTables, computeThirdPlaceTable } from "@/lib/standings"; import { qualifiedThirdGroups, resolveAnnexC } from "@/lib/bracket"; // Diese Route wird vom Frontend gepollt. Sie ist der einzige Ort, der die // Upstream-Feeds berührt — gecacht, damit Rate Limits eingehalten werden. export const dynamic = "force-dynamic"; export async function GET() { try { const { matches: rawMatches, teams } = await fetchMatchesAndTeams(); // Odds sind optional: fällt der Polymarket-Call aus, liefern wir trotzdem. let matches = rawMatches; try { const odds = await fetchOdds(); matches = attachOdds(rawMatches, teams, odds); } catch (err) { console.error("[polymarket] fetchOdds fehlgeschlagen:", err); } // Live-Scores von worldcup26.ir (additiv, Fallback auf football-data) try { const liveScores = await fetchLiveScores(); matches = applyLiveScores(matches, teams, liveScores); } catch (err) { console.error("[worldcup26] fetchLiveScores fehlgeschlagen:", err); } const groupTables = computeGroupTables(teams, matches); const groupTablesLive = computeGroupTables(teams, matches, true); // K.o.-Match-Nummern per Slot-Auflösung vergeben (FIFA-Topologie) assignKONumbersBySlots(matches, teams); // prob-Feld normalisieren: immer null statt undefined, damit JSON konsistent ist const normalizedMatches = matches.map((m) => ({ ...m, prob: m.prob ?? null })); const thirdTable = computeThirdPlaceTable(groupTablesLive); const qGroups = qualifiedThirdGroups(thirdTable); const annex = qGroups.length === 8 ? resolveAnnexC(qGroups) : null; return NextResponse.json({ updatedAt: new Date().toISOString(), teams, matches: normalizedMatches, groupTables, groupTablesLive, thirdTable, annexAssignment: annex, annexResolved: annex != null, }); } catch (err) { const message = err instanceof Error ? err.message : "unbekannter Fehler"; return NextResponse.json( { error: "Feed nicht erreichbar", detail: message }, { status: 502 }, ); } }