"use client";

import {
  Badge,
  Box,
  Card,
  Flex,
  Grid,
  HStack,
  Icon,
  IconButton,
  Separator,
  SimpleGrid,
  Text,
  VStack,
} from "@chakra-ui/react";
import { useMessages, useTranslations } from "next-intl";
import {
  LuBadgeCheck,
  LuBrain,
  LuChartColumn,
  LuChartNoAxesCombined,
  LuCircleHelp,
  LuFlame,
  LuGauge,
  LuShieldAlert,
  LuSparkles,
  LuTarget,
  LuTriangleAlert,
  LuTrendingUp,
} from "react-icons/lu";
import { useColorModeValue } from "@/components/ui/color-mode";
import { Tooltip } from "@/components/ui/overlays/tooltip";
import type {
  MarketBoardEntryDto,
  MatchBetSummaryItemDto,
  MatchPickDto,
  MatchPredictionDto,
  SignalTier,
  V27EngineDto,
} from "@/lib/api/predictions/types";
import type { SportType } from "@/lib/api/matches/types";
import V28OddsBandPanel from "@/components/matches/v28-odds-band-panel";

interface PredictionCardProps {
  prediction: MatchPredictionDto;
}

type PredictionUiMessages = Record<string, string>;

function getUiText(
  ui: PredictionUiMessages | undefined,
  key: string,
  fallback: string,
): string {
  return ui?.[key] || fallback;
}

function formatReasonFallback(reason: string): string {
  if (reason.startsWith("risk:")) return formatReasonFallback(reason.slice(5));
  const evMatch = reason.match(/^ev_edge_([+\-][\d.]+%)_grade_(\w)$/);
  if (evMatch) return `Teorik avantaj sinyali: Not ${evMatch[2]}`;
  const negMatch = reason.match(/^negative_model_edge_([+\-][\d.]+)$/);
  if (negMatch) return `Model avantajı negatif (${negMatch[1]})`;
  const thresholdMatch = reason.match(
    /^below_market_edge_threshold_([+\-]?[\d.]+)$/,
  );
  if (thresholdMatch)
    return `Piyasa avantaj eşiğinin altında (${thresholdMatch[1]})`;
  if (reason === "confidence_interval_too_wide")
    return "Güven aralığı fazla geniş.";
  if (reason === "confidence_band_low") return "Güven bandı düşük.";
  if (reason === "draw_probability_elevated")
    return "Beraberlik olasılığı yükselmiş görünüyor.";
  if (reason === "balanced_match_risk")
    return "Maç dengeli görünüyor, sürpriz riski var.";
  if (reason === "high_total_goal_volatility")
    return "Yüksek gol temposu sürpriz riskini artırıyor.";
  if (reason === "mutual_goal_pressure")
    return "İki takım da gol tehdidi üretiyor.";
  if (reason === "late_goal_swing_risk")
    return "Geç gol veya skor kırılması riski yüksek.";
  if (reason === "live_match_open_state")
    return "Canlı maç tamamen açık oyuna dönmüş durumda.";
  if (reason === "live_match_active_state")
    return "Canlı maç beklenenden daha hareketli ilerliyor.";
  if (reason === "live_state_impossible_market")
    return "Canlı maç durumu bu marketi geçersiz kılıyor.";
  if (reason === "live_score_exceeds_under_line")
    return "Canlı skor, alt seçeneğinin üst sınırına çok yaklaştı veya geçti.";
  if (reason === "score_model_conflicts_with_under_pick")
    return "Skor ve xG modeli bu alt seçeneğiyle çelişiyor.";
  if (reason === "score_model_conflicts_with_over_pick")
    return "Skor ve xG modeli bu üst seçeneğiyle çelişiyor.";
  if (reason === "market_stack_conflict_over25")
    return "2.5 üst sinyali bu marketle çelişiyor.";
  if (reason === "market_stack_conflict_btts")
    return "KG Var sinyali bu marketle çelişiyor.";
  if (reason === "live_total_goals_close_to_line")
    return "Canlı toplam gol sayısı bu çizgiye fazla yaklaştı.";
  if (reason === "score_model_conflicts_with_btts_no")
    return "Skor ve xG modeli KG Yok seçeneğiyle çelişiyor.";
  if (reason === "score_model_conflicts_with_draw_pick")
    return "Skor modeli beraberlik seçeneğini desteklemiyor.";
  if (reason === "score_model_conflicts_with_home_pick")
    return "Skor modeli ev sahibi seçeneğini desteklemiyor.";
  if (reason === "score_model_conflicts_with_away_pick")
    return "Skor modeli deplasman seçeneğini desteklemiyor.";
  if (/^[a-z0-9_]+$/i.test(reason)) {
    return reason
      .replace(/_/g, " ")
      .replace(/^\w/, (char) => char.toUpperCase());
  }
  return reason;
}

function formatPercent(value?: number, digits = 0): string {
  if (value === undefined || value === null || Number.isNaN(value)) return "-";
  return `${value.toFixed(digits)}%`;
}

function formatProbability(value?: number, digits = 1): string {
  if (value === undefined || value === null || Number.isNaN(value)) return "-";
  return `${(value * 100).toFixed(digits)}%`;
}

function formatSignalScore(value?: number): string {
  if (value === undefined || value === null || Number.isNaN(value)) return "-";
  return `${Math.max(0, Math.min(100, value)).toFixed(0)}/100`;
}

function formatEdgeSignal(value?: number): string {
  if (value === undefined || value === null || Number.isNaN(value)) return "-";
  return `${value > 0 ? "+" : ""}${formatPercent(value * 100, 1)}`;
}

function getEdgePalette(value?: number): string {
  if (value === undefined || value === null || Number.isNaN(value))
    return "gray";
  if (value <= 0) return "red";
  if (value < 0.08) return "yellow";
  if (value < 0.15) return "orange";
  return "purple";
}

function formatOdds(value?: number | null): string {
  if (!value || value <= 1.01) return "-";
  return value.toFixed(2);
}

function formatUnits(value?: number): string {
  if (!value || value <= 0) return "-";
  return `${value.toFixed(1)}u`;
}

function getEngineLabelPalette(label?: string): string {
  switch ((label || "").toUpperCase()) {
    case "YUKSEK":
      return "green";
    case "ORTA":
      return "yellow";
    case "DUSUK":
      return "orange";
    case "COK_DUSUK":
      return "red";
    default:
      return "gray";
  }
}

function getEngineLabelText(label?: string, ui?: PredictionUiMessages): string {
  switch ((label || "").toUpperCase()) {
    case "YUKSEK":
      return getUiText(ui, "engine-label-high", "Yüksek");
    case "ORTA":
      return getUiText(ui, "engine-label-medium", "Orta");
    case "DUSUK":
      return getUiText(ui, "engine-label-low", "Düşük");
    case "COK_DUSUK":
      return getUiText(ui, "engine-label-very-low", "Çok Düşük");
    default:
      return label || "";
  }
}

function getRiskPalette(level: string) {
  switch (level.toUpperCase()) {
    case "LOW":
      return "green";
    case "MEDIUM":
      return "yellow";
    case "HIGH":
      return "orange";
    case "EXTREME":
      return "red";
    default:
      return "gray";
  }
}

function getQualityPalette(label: string) {
  switch (label.toUpperCase()) {
    case "HIGH":
      return "green";
    case "MEDIUM":
      return "yellow";
    case "LOW":
      return "red";
    default:
      return "gray";
  }
}

function getConfidenceBandPalette(band?: string) {
  switch ((band || "").toUpperCase()) {
    case "HIGH":
      return "green";
    case "MEDIUM":
      return "yellow";
    case "LOW":
      return "red";
    default:
      return "gray";
  }
}

function getConfidenceBandLabel(band?: string, ui?: PredictionUiMessages) {
  switch ((band || "").toUpperCase()) {
    case "HIGH":
      return getUiText(ui, "confidence-high", "Yüksek");
    case "MEDIUM":
      return getUiText(ui, "confidence-medium", "Orta");
    case "LOW":
      return getUiText(ui, "confidence-low", "Düşük");
    default:
      return getUiText(ui, "confidence-unknown", "Belirsiz");
  }
}

function getLineupSourceLabel(
  source?: string,
  ui?: PredictionUiMessages,
): string {
  if (source === "confirmed_live")
    return getUiText(ui, "lineup-confirmed-live", "Onaylı ilk 11");
  if (source === "probable_xi")
    return getUiText(ui, "lineup-probable-xi", "Muhtemel ilk 11");
  return source
    ? formatReasonFallback(source)
    : getUiText(ui, "unknown", "Bilinmiyor");
}

function formatInterval(
  interval?: { lower?: number; upper?: number },
  digits = 0,
): string {
  if (
    !interval ||
    interval.lower === undefined ||
    interval.upper === undefined ||
    Number.isNaN(interval.lower) ||
    Number.isNaN(interval.upper)
  ) {
    return "-";
  }
  return `${interval.lower.toFixed(digits)}-${interval.upper.toFixed(digits)}%`;
}

function getPredictionReasonText(
  reason: string,
  reasonMessages?: Record<string, string>,
): string {
  if (
    reasonMessages &&
    Object.prototype.hasOwnProperty.call(reasonMessages, reason)
  ) {
    return reasonMessages[reason];
  }
  return formatReasonFallback(reason);
}

function getMarketLabel(
  market: string,
  marketLabels?: Record<string, string>,
): string {
  if (
    marketLabels &&
    Object.prototype.hasOwnProperty.call(marketLabels, market)
  ) {
    return marketLabels[market];
  }

  const fallbackLabels: Record<string, string> = {
    ML: "Moneyline",
    MS: "Maç Sonucu",
    DC: "Çifte Şans",
    TOTAL: "Toplam Sayı",
    SPREAD: "Handikap",
    OU15: "Toplam Gol 1.5",
    OU25: "Toplam Gol 2.5",
    OU35: "Toplam Gol 3.5",
    BTTS: "Karşılıklı Gol",
    HT: "İlk Yarı Sonucu",
    HT_OU05: "İlk Yarı 0.5 Gol",
    HT_OU15: "İlk Yarı 1.5 Gol",
    HTFT: "İlk Yarı / Maç Sonu",
    "HT/FT": "İlk Yarı / Maç Sonu",
    OE: "Tek / Çift",
    CARDS: "Kartlar 4.5",
    HCAP: "Handikap Sonucu",
  };
  if (fallbackLabels[market]) {
    return fallbackLabels[market];
  }

  return market;
}

const MARKET_ORDER = [
  "ML",
  "TOTAL",
  "SPREAD",
  "MS",
  "DC",
  "OU15",
  "OU25",
  "OU35",
  "BTTS",
  "HT",
  "HT_OU05",
  "HT_OU15",
  "HTFT",
  "OE",
  "CARDS",
  "HCAP",
];

function getPredictionSport(prediction: MatchPredictionDto): SportType {
  const explicitSport = prediction.match_info?.sport;
  if (explicitSport === "basketball" || explicitSport === "football") {
    return explicitSport;
  }

  if (
    prediction.model_version?.toLowerCase().includes("basketball") ||
    Object.keys(prediction.market_board || {}).some((market) =>
      ["ML", "TOTAL", "SPREAD"].includes(market),
    )
  ) {
    return "basketball";
  }

  return "football";
}

const SIGNAL_TIER_ORDER: SignalTier[] = [
  "CORE",
  "VALUE",
  "LEAN",
  "LONGSHOT",
  "PASS",
];

function getSignalTierPalette(tier?: SignalTier) {
  switch (tier) {
    case "CORE":
      return "green";
    case "VALUE":
      return "blue";
    case "LEAN":
      return "orange";
    case "LONGSHOT":
      return "pink";
    default:
      return "gray";
  }
}

function getSignalTierLabel(tier?: SignalTier, ui?: PredictionUiMessages) {
  switch (tier) {
    case "CORE":
      return getUiText(ui, "signal-tier-core", "Çekirdek");
    case "VALUE":
      return getUiText(ui, "signal-tier-value", "Değer");
    case "LEAN":
      return getUiText(ui, "signal-tier-lean", "Yorum");
    case "LONGSHOT":
      return getUiText(ui, "signal-tier-longshot", "Sürpriz");
    default:
      return getUiText(ui, "signal-tier-pass", "Pas");
  }
}

function TooltipIcon({
  content,
  ariaLabel = "Bilgi",
}: {
  content: string;
  ariaLabel?: string;
}) {
  return (
    <Tooltip
      content={content}
      showArrow
      positioning={{ placement: "top" }}
      contentProps={{ maxW: "260px", fontSize: "xs", px: 3, py: 2 }}
    >
      <IconButton
        aria-label={ariaLabel}
        variant="ghost"
        size="2xs"
        colorPalette="gray"
      >
        <LuCircleHelp />
      </IconButton>
    </Tooltip>
  );
}

function SectionTitle({
  icon,
  title,
  info,
}: {
  icon: React.ElementType;
  title: string;
  info?: string;
}) {
  return (
    <HStack justify="space-between" w="full">
      <HStack gap={2}>
        <Icon as={icon} boxSize={4.5} color="fg.muted" />
        <Text fontSize="lg" fontWeight="semibold">
          {title}
        </Text>
      </HStack>
      {info ? <TooltipIcon content={info} /> : null}
    </HStack>
  );
}

function MetricTile({
  label,
  value,
  helper,
  accent,
}: {
  label: string;
  value: string;
  helper?: string;
  accent?: string;
}) {
  const bg = useColorModeValue("gray.50", "whiteAlpha.50");
  const borderColor = useColorModeValue("gray.200", "gray.700");
  return (
    <Box
      p={3.5}
      bg={bg}
      borderWidth="1px"
      borderColor={borderColor}
      borderRadius="xl"
    >
      <HStack justify="space-between" mb={1.5}>
        <Text fontSize="xs" color="fg.muted" fontWeight="medium">
          {label}
        </Text>
        {helper ? <TooltipIcon content={helper} /> : null}
      </HStack>
      <Text fontSize="xl" fontWeight="bold" color={accent}>
        {value}
      </Text>
    </Box>
  );
}

function Bar({
  value,
  color,
  trackBg,
  height = "8px",
}: {
  value: number;
  color: string;
  trackBg: string;
  height?: string;
}) {
  return (
    <Box h={height} w="full" bg={trackBg} borderRadius="full" overflow="hidden">
      <Box
        h="full"
        w={`${Math.max(0, Math.min(100, value))}%`}
        bg={color}
        borderRadius="full"
      />
    </Box>
  );
}

function ReasonList({
  items,
  resolveReason,
}: {
  items?: string[];
  resolveReason: (reason: string) => string;
}) {
  if (!items?.length) return null;
  return (
    <VStack align="stretch" gap={1.5}>
      {items.map((item, index) => (
        <HStack key={`${item}-${index}`} align="start" gap={2}>
          <Box mt="7px" boxSize="5px" bg="primary.400" borderRadius="full" />
          <Text fontSize="sm" color="fg.muted" lineHeight="tall">
            {resolveReason(item)}
          </Text>
        </HStack>
      ))}
    </VStack>
  );
}

function ProbabilitySplit({
  modelProb,
  impliedProb,
  labels,
}: {
  modelProb: number;
  impliedProb: number;
  labels: {
    model: string;
    market: string;
  };
}) {
  const trackBg = useColorModeValue("gray.100", "gray.700");
  if (!impliedProb || impliedProb <= 0) return null;
  return (
    <VStack align="stretch" gap={2}>
      <Flex justify="space-between">
        <Text fontSize="xs" color="blue.600" fontWeight="semibold">
          {labels.model} {formatProbability(modelProb, 0)}
        </Text>
        <Text fontSize="xs" color="orange.500" fontWeight="semibold">
          {labels.market} {formatProbability(impliedProb, 0)}
        </Text>
      </Flex>
      <Box position="relative">
        <Bar value={modelProb * 100} color="blue.400" trackBg={trackBg} />
        <Box
          position="absolute"
          top="-2px"
          left={`calc(${Math.min(impliedProb * 100, 100)}% - 1px)`}
          h="12px"
          w="2px"
          bg="orange.500"
          borderRadius="full"
        />
      </Box>
    </VStack>
  );
}

function PickCard({
  pick,
  stakeFallback,
  title,
  resolveReason,
  palette,
  marketLabels,
  labels,
  ui,
}: {
  pick: MatchPickDto;
  stakeFallback?: number;
  title: string;
  resolveReason: (reason: string) => string;
  palette: string;
  marketLabels?: Record<string, string>;
  ui?: PredictionUiMessages;
  labels: {
    confidence: string;
    odds: string;
    recommendedStake: string;
    playScore: string;
    playability: string;
    confidenceInterval: string;
    confidenceBand: string;
    confidenceIntervalWarning: string;
    theoreticalEdgeInline: string;
    modelProbability: string;
    marketProbability: string;
  };
}) {
  const bg = useColorModeValue(`${palette}.50`, `${palette}.950`);
  const borderColor = useColorModeValue(`${palette}.200`, `${palette}.800`);
  const trackBg = useColorModeValue("gray.100", "gray.700");
  const intervalWarningBg = useColorModeValue("orange.50", "orange.950");
  const intervalWarningBorder = useColorModeValue("orange.200", "orange.800");
  const confidenceBandPalette = getConfidenceBandPalette(
    pick.confidence_interval?.band,
  );
  return (
    <Card.Root bg={bg} borderColor={borderColor} borderRadius="2xl">
      <Card.Body gap={4}>
        <Flex
          justify="space-between"
          align={{ base: "start", md: "center" }}
          direction={{ base: "column", md: "row" }}
          gap={3}
        >
          <VStack align="start" gap={2}>
            <Badge colorPalette={palette} variant="solid" borderRadius="full">
              {title}
            </Badge>
            <Text fontSize="2xl" fontWeight="bold">
              {pick.pick}
            </Text>
            <Text fontSize="xs" color="fg.muted" maxW="380px">
              {getUiText(
                ui,
                "value-bet-framing",
                "Bu, maçın en olası sonucu DEĞİL — orana göre uzun vadede kârlı görülen değer bahsidir. Tek başına tutma olasılığı düşük olabilir.",
              )}
            </Text>
            <HStack gap={2} flexWrap="wrap">
              <Badge variant="subtle">
                {getMarketLabel(pick.market, marketLabels)}
              </Badge>
              <Badge
                colorPalette={pick.playable ? "green" : "gray"}
                variant="subtle"
              >
                {pick.bet_grade}
              </Badge>
              <Badge
                colorPalette={getSignalTierPalette(pick.signal_tier)}
                variant="subtle"
              >
                {getSignalTierLabel(pick.signal_tier, ui)}
              </Badge>
              <Badge colorPalette={confidenceBandPalette} variant="subtle">
                {getConfidenceBandLabel(pick.confidence_interval?.band, ui)}
              </Badge>
              <Badge
                colorPalette={getEdgePalette(pick.ev_edge)}
                variant="subtle"
              >
                {labels.theoreticalEdgeInline} {formatEdgeSignal(pick.ev_edge)}
              </Badge>
            </HStack>
          </VStack>
          <SimpleGrid columns={2} gap={3} minW={{ base: "full", md: "320px" }}>
            <MetricTile
              label={labels.confidence}
              value={formatPercent(pick.unified_score ?? pick.calibrated_confidence, 0)}
            />
            <MetricTile label={labels.odds} value={formatOdds(pick.odds)} />
            <MetricTile
              label={labels.recommendedStake}
              value={formatUnits(pick.stake_units || stakeFallback)}
            />
            <MetricTile
              label={labels.playScore}
              value={formatSignalScore(pick.play_score)}
            />
            <MetricTile
              label={labels.confidenceInterval}
              value={formatInterval(pick.confidence_interval)}
            />
            <MetricTile
              label={labels.confidenceBand}
              value={getConfidenceBandLabel(pick.confidence_interval?.band, ui)}
              accent={`${confidenceBandPalette}.500`}
            />
          </SimpleGrid>
        </Flex>
        <ProbabilitySplit
          modelProb={pick.probability}
          impliedProb={pick.implied_prob}
          labels={{
            model: labels.modelProbability,
            market: labels.marketProbability,
          }}
        />
        <Box>
          <HStack justify="space-between" mb={1.5}>
            <Text fontSize="sm" fontWeight="semibold">
              {labels.playability}
            </Text>
            <Text fontSize="sm" color="fg.muted">
              {formatSignalScore(pick.play_score)}
            </Text>
          </HStack>
          <Bar
            value={pick.play_score}
            color={pick.ev_edge > 0 ? "blue.400" : "orange.400"}
            trackBg={trackBg}
          />
        </Box>
        <ReasonList
          items={pick.decision_reasons}
          resolveReason={resolveReason}
        />
        {pick.confidence_interval && !pick.confidence_interval.threshold_met ? (
          <Box
            p={3}
            borderRadius="xl"
            bg={intervalWarningBg}
            borderWidth="1px"
            borderColor={intervalWarningBorder}
          >
            <Text fontSize="sm" color="fg.muted">
              {labels.confidenceIntervalWarning}
            </Text>
          </Box>
        ) : null}
      </Card.Body>
    </Card.Root>
  );
}

function SummaryTable({
  items,
  marketLabels,
  title,
  info,
  ui,
}: {
  items: MatchBetSummaryItemDto[];
  marketLabels?: Record<string, string>;
  title: string;
  info: string;
  ui?: PredictionUiMessages;
}) {
  const cardBg = useColorModeValue("white", "gray.800");
  const borderColor = useColorModeValue("gray.200", "gray.700");
  const highlightBg = useColorModeValue("green.50", "green.950");
  if (!items.length) return null;
  return (
    <Card.Root bg={cardBg} borderColor={borderColor} borderRadius="2xl">
      <Card.Body gap={4}>
        <SectionTitle icon={LuChartColumn} title={title} info={info} />
        <VStack align="stretch" gap={2}>
          {items
            .slice()
            .sort((left, right) => {
              const leftIndex = SIGNAL_TIER_ORDER.indexOf(
                left.signal_tier || "PASS",
              );
              const rightIndex = SIGNAL_TIER_ORDER.indexOf(
                right.signal_tier || "PASS",
              );
              if (leftIndex !== rightIndex) return leftIndex - rightIndex;
              return (right.unified_score ?? right.calibrated_confidence) - (left.unified_score ?? left.calibrated_confidence);
            })
            .map((item) => (
              <Flex
                key={`${item.market}-${item.pick}`}
                justify="space-between"
                align={{ base: "start", md: "center" }}
                direction={{ base: "column", md: "row" }}
                gap={3}
                px={3}
                py={3}
                borderRadius="xl"
                bg={item.playable ? highlightBg : "transparent"}
                borderWidth="1px"
                borderColor={item.playable ? "green.200" : borderColor}
              >
                <HStack gap={2} flexWrap="wrap">
                  <Badge
                    colorPalette={item.playable ? "green" : "gray"}
                    variant="subtle"
                  >
                    {item.bet_grade}
                  </Badge>
                  <Badge
                    colorPalette={getSignalTierPalette(item.signal_tier)}
                    variant="subtle"
                  >
                    {getSignalTierLabel(item.signal_tier, ui)}
                  </Badge>
                  <Text fontWeight="semibold">
                    {getMarketLabel(item.market, marketLabels)}
                  </Text>
                  <Text color="fg.muted">{item.pick}</Text>
                </HStack>
                <HStack gap={5} fontSize="sm">
                  <Text minW="48px">{formatOdds(item.odds)}</Text>
                  <Text minW="64px" color="fg.muted">
                    {formatPercent(
                      (item.model_probability ?? 0) * 100,
                      0,
                    )}{" "}
                    {getUiText(ui, "probability-short", "olasılık")}
                  </Text>
                  <Text
                    minW="96px"
                    color={`${getEdgePalette(item.ev_edge)}.500`}
                    fontWeight="semibold"
                  >
                    {formatEdgeSignal(item.ev_edge)}
                  </Text>
                  <Text minW="48px">
                    {formatPercent(item.unified_score ?? item.calibrated_confidence, 0)}
                  </Text>
                  <Badge
                    colorPalette={getConfidenceBandPalette(
                      item.confidence_interval?.band,
                    )}
                    variant="subtle"
                  >
                    {getConfidenceBandLabel(item.confidence_interval?.band, ui)}
                  </Badge>
                  <Badge variant="surface">
                    {formatUnits(item.stake_units)}
                  </Badge>
                </HStack>
              </Flex>
            ))}
          {/* <Flex
            key={`${item.market}-${item.pick}`}
            justify="space-between"
            align={{ base: "start", md: "center" }}
            direction={{ base: "column", md: "row" }}
            gap={3}
            px={3}
            py={3}
            borderRadius="xl"
            bg={item.playable ? highlightBg : "transparent"}
            borderWidth="1px"
            borderColor={item.playable ? "green.200" : borderColor}
          >
            <HStack gap={2} flexWrap="wrap">
              <Badge colorPalette={item.playable ? "green" : "gray"} variant="subtle">
                {item.bet_grade}
              </Badge>
              <Badge colorPalette={getSignalTierPalette(item.signal_tier)} variant="subtle">
                {getSignalTierLabel(item.signal_tier)}
              </Badge>
              {item.is_underdog_reference ? (
                <Badge colorPalette="gray" variant="outline" title={getUiText(ui, "underdog-ref-tooltip", "Underdog tarafının model olasılığı (bilgi amaçlı)")}>
                  Underdog ref.
                </Badge>
              ) : null}
              {item.betting_brain?.trap_market_flag ? (
                <Badge colorPalette="red" variant="subtle" title={`${getUiText(ui, "trap-tooltip", "Piyasa aşırı güveniyor")} (gap ${((item.betting_brain.trap_market_gap || 0) * 100) | 0}pp)`}>
                  Trap
                </Badge>
              ) : null}
              {item.betting_brain?.action === "WATCH_NO_VALUE" ? (
                <Badge colorPalette="orange" variant="subtle" title={getUiText(ui, "no-value-tooltip", "Model favoriyle hemfikir ama oran çok düşük")}>
                  No-value
                </Badge>
              ) : null}
              <Text fontWeight="semibold">{getMarketLabel(item.market, marketLabels)}</Text>
              <Text color="fg.muted">{item.pick}</Text>
            </HStack>
            <HStack gap={5} fontSize="sm">
              <Text minW="48px">{formatOdds(item.odds)}</Text>
              <Text minW="68px" color={item.ev_edge > 0 ? "green.500" : "red.500"} fontWeight="semibold">
                {item.ev_edge > 0 ? "+" : ""}
                {formatPercent(item.ev_edge * 100, 1)}
              </Text>
              <Text minW="48px">{formatPercent(item.calibrated_confidence, 0)}</Text>
              <Badge colorPalette={getConfidenceBandPalette(item.confidence_interval?.band)} variant="subtle">
                {getConfidenceBandLabel(item.confidence_interval?.band)}
              </Badge>
              <Badge variant="surface">{formatUnits(item.stake_units)}</Badge>
            </HStack>
          </Flex> */}
        </VStack>
      </Card.Body>
    </Card.Root>
  );
}

function MarketBoardSection({
  marketBoard,
  betSummary,
  marketLabels,
  title,
  info,
  ui,
}: {
  marketBoard?: Record<string, MarketBoardEntryDto>;
  betSummary?: MatchBetSummaryItemDto[];
  marketLabels?: Record<string, string>;
  title: string;
  info: string;
  ui?: PredictionUiMessages;
}) {
  const cardBg = useColorModeValue("white", "gray.800");
  const borderColor = useColorModeValue("gray.200", "gray.700");
  const trackBg = useColorModeValue("gray.100", "gray.700");
  const innerBg = useColorModeValue("gray.50", "whiteAlpha.50");

  if (!marketBoard || !Object.keys(marketBoard).length) return null;

  // Key by market:pick so each card resolves the summary row for the EXACT
  // outcome it displays (graph pick). Keying by market alone collided on
  // multi-row markets (MS 1/X/2) and surfaced the wrong odds + confidence.
  const summaryByMarket = new Map(
    (betSummary || []).map((item) => [`${item.market}:${item.pick}`, item]),
  );
  // Fallback: first row of a market, for cards whose pick has no exact row.
  for (const item of betSummary || []) {
    if (!summaryByMarket.has(item.market)) {
      summaryByMarket.set(item.market, item);
    }
  }
  const orderedEntries = Object.entries(marketBoard).sort(([left], [right]) => {
    const leftIndex = MARKET_ORDER.indexOf(left);
    const rightIndex = MARKET_ORDER.indexOf(right);
    const safeLeft = leftIndex === -1 ? Number.MAX_SAFE_INTEGER : leftIndex;
    const safeRight = rightIndex === -1 ? Number.MAX_SAFE_INTEGER : rightIndex;
    return safeLeft - safeRight;
  });

  return (
    <Card.Root bg={cardBg} borderColor={borderColor} borderRadius="2xl">
      <Card.Body gap={4}>
        <SectionTitle icon={LuChartNoAxesCombined} title={title} info={info} />
        <SimpleGrid columns={{ base: 1, xl: 2 }} gap={4}>
          {orderedEntries.map(([market, entry]) => {
            if (!entry?.probs) return null;
            const summary =
              summaryByMarket.get(`${market}:${entry.pick}`) ??
              summaryByMarket.get(market);
            const interval =
              summary?.confidence_interval || entry.confidence_interval;
            // Hit probability == the dominant (green) bar in the graph below,
            // so the headline never contradicts the distribution it sits on.
            const pickProbPct =
              Math.max(
                0,
                ...Object.values(entry.probs).map((p) => Number(p) || 0),
              ) * 100;
            return (
              <Box
                key={market}
                p={4}
                bg={innerBg}
                borderWidth="1px"
                borderColor={borderColor}
                borderRadius="xl"
              >
                <Flex justify="space-between" align="start" mb={3}>
                  <VStack align="start" gap={1}>
                    <Text fontWeight="semibold">{market}</Text>
                    <Text fontSize="sm" color="fg.muted">
                      {getMarketLabel(market, marketLabels)}
                    </Text>
                    <HStack gap={2} flexWrap="wrap">
                      {summary ? (
                        <Badge
                          colorPalette={summary.playable ? "green" : "gray"}
                          variant="subtle"
                        >
                          {summary.playable
                            ? getUiText(ui, "playable", "Oynanabilir")
                            : getUiText(ui, "risky", "Riskli")}
                        </Badge>
                      ) : null}
                      {summary?.signal_tier ? (
                        <Badge
                          colorPalette={getSignalTierPalette(
                            summary.signal_tier,
                          )}
                          variant="subtle"
                        >
                          {getSignalTierLabel(summary.signal_tier, ui)}
                        </Badge>
                      ) : null}
                      {summary?.bet_grade ? (
                        <Badge variant="outline">{summary.bet_grade}</Badge>
                      ) : null}
                    </HStack>
                  </VStack>
                  {entry.pick ? (
                    <Badge
                      colorPalette={getConfidenceBandPalette(
                        entry.confidence_band || interval?.band,
                      )}
                      variant="subtle"
                      borderRadius="full"
                    >
                      {entry.pick} ({formatPercent(pickProbPct, 0)})
                    </Badge>
                  ) : null}
                </Flex>
                <SimpleGrid columns={3} gap={2} mb={3}>
                  <MetricTile
                    label={getUiText(ui, "hit-probability", "Tutma Olasılığı")}
                    value={formatPercent(pickProbPct, 0)}
                    accent="green.500"
                  />
                  <MetricTile
                    label={getUiText(
                      ui,
                      "unified-confidence",
                      "Güven Skoru",
                    )}
                    value={
                      summary
                        ? formatPercent(summary.unified_score ?? summary.calibrated_confidence, 0)
                        : "-"
                    }
                    accent={summary?.playable ? "green.500" : "orange.500"}
                  />
                  <MetricTile
                    label="Oran"
                    value={summary ? formatOdds(summary.odds) : "-"}
                  />
                </SimpleGrid>
                {interval ? (
                  <Text fontSize="xs" color="fg.muted" mb={3}>
                    {getUiText(ui, "confidence-interval", "Güven Aralığı")}:{" "}
                    {formatInterval(interval)}
                  </Text>
                ) : null}
                <VStack align="stretch" gap={2.5}>
                  {Object.entries(entry.probs).map(([outcome, probability]) => (
                    <Box key={`${market}-${outcome}`}>
                      <Flex justify="space-between" mb={1}>
                        <Text fontSize="sm" color="fg.muted">
                          {outcome.toUpperCase()}
                        </Text>
                        <Text fontSize="sm" fontWeight="semibold">
                          {formatProbability(probability, 1)}
                        </Text>
                      </Flex>
                      <Bar
                        value={probability * 100}
                        color={
                          (Number(probability) || 0) * 100 >= pickProbPct - 1e-6
                            ? "green.400"
                            : "blue.400"
                        }
                        trackBg={trackBg}
                        height="6px"
                      />
                    </Box>
                  ))}
                </VStack>
              </Box>
            );
          })}
        </SimpleGrid>
      </Card.Body>
    </Card.Root>
  );
}

function ScoreCard({
  prediction,
  sport,
  ui,
}: {
  prediction: MatchPredictionDto;
  sport: SportType;
  ui?: PredictionUiMessages;
}) {
  const cardBg = useColorModeValue("white", "gray.800");
  const borderColor = useColorModeValue("gray.200", "gray.700");
  const subBg = useColorModeValue("gray.50", "whiteAlpha.50");
  const isBasketball = sport === "basketball";

  return (
    <Card.Root bg={cardBg} borderColor={borderColor} borderRadius="2xl">
      <Card.Body gap={4}>
        <SectionTitle
          icon={LuTarget}
          title={
            isBasketball
              ? getUiText(ui, "score-scenario-basketball", "Sayı Senaryosu")
              : getUiText(ui, "score-scenario-football", "Skor Senaryosu")
          }
          info={
            isBasketball
              ? getUiText(
                  ui,
                  "score-scenario-info-basketball",
                  "Beklenen sayı dağılımı ve en olası maç senaryoları.",
                )
              : getUiText(
                  ui,
                  "score-scenario-info-football",
                  "Beklenen skor ve en olası senaryolar.",
                )
          }
        />
        <SimpleGrid columns={{ base: 1, md: 3 }} gap={3}>
          <MetricTile
            label={
              isBasketball
                ? getUiText(ui, "full-time-basketball", "Maç Sonu Sayı")
                : getUiText(ui, "full-time-football", "Maç Sonu")
            }
            value={prediction.score_prediction.ft}
          />
          <MetricTile
            label={
              isBasketball
                ? getUiText(ui, "half-time-basketball", "İlk Yarı Sayı")
                : getUiText(ui, "half-time-football", "İlk Yarı")
            }
            value={prediction.score_prediction.ht}
          />
          <MetricTile
            label={
              isBasketball
                ? getUiText(
                    ui,
                    "expected-total-basketball",
                    "Beklenen Toplam Sayı",
                  )
                : getUiText(ui, "expected-total-football", "Toplam xG")
            }
            value={prediction.score_prediction.xg_total.toFixed(2)}
          />
        </SimpleGrid>
        <SimpleGrid columns={{ base: 2, md: 5 }} gap={2}>
          {prediction.scenario_top5.map((scenario) => (
            <Box
              key={`${scenario.score}-${scenario.prob}`}
              p={3}
              bg={subBg}
              borderWidth="1px"
              borderColor={borderColor}
              borderRadius="xl"
            >
              <Text fontSize="lg" fontWeight="bold">
                {scenario.score}
              </Text>
              <Text fontSize="sm" color="fg.muted">
                {formatProbability(scenario.prob, 1)}
              </Text>
            </Box>
          ))}
        </SimpleGrid>
      </Card.Body>
    </Card.Root>
  );
}

export default function PredictionCard({ prediction }: PredictionCardProps) {
  const t = useTranslations("predictions");
  const messages = useMessages() as {
    predictions?: {
      "prediction-reasons"?: Record<string, string>;
      "market-labels"?: Record<string, string>;
      ui?: Record<string, string>;
    };
  };
  const marketLabels = messages.predictions?.["market-labels"];
  const ui = messages.predictions?.ui;
  const uiText = (key: string, fallback: string) => ui?.[key] || fallback;
  const resolveReason = (reason: string) =>
    getPredictionReasonText(
      reason,
      messages.predictions?.["prediction-reasons"],
    );

  const pageBg = useColorModeValue("gray.50", "gray.900");
  const cardBg = useColorModeValue("white", "gray.800");
  const borderColor = useColorModeValue("gray.200", "gray.700");
  const liveBg = useColorModeValue("red.50", "red.950");
  const liveBorderColor = useColorModeValue("red.300", "red.800");
  const warningBg = useColorModeValue("yellow.50", "yellow.950");
  const warningBorderColor = useColorModeValue("yellow.300", "yellow.800");
  const orangeBg = useColorModeValue("orange.50", "orange.950");
  const orangeBorderColor = useColorModeValue("orange.200", "orange.800");
  const greenBg = useColorModeValue("green.50", "green.950");
  const greenBorderColor = useColorModeValue("green.200", "green.800");
  const statCardBg = useColorModeValue("gray.50", "whiteAlpha.50");
  const trackBgColor = useColorModeValue("gray.100", "gray.700");
  const mrPredBg = useColorModeValue("blue.50", "blue.950");
  const mrPredBorder = useColorModeValue("blue.300", "blue.700");
  const riskPalette = getRiskPalette(prediction.risk.level);
  const qualityPalette = getQualityPalette(prediction.data_quality.label);
  const recommendedPick = prediction.main_pick;
  const mainBandPalette = getConfidenceBandPalette(
    prediction.bet_advice.confidence_band,
  );

  // ── Maç Sonucu Tahmini (model'in EN OLASI sonucu) ──────────────────
  // The value-bet hero below optimizes ROI (often a high-odds draw/underdog,
  // ~27% hit) which users misread as a "bad prediction". This block instead
  // shows what the model thinks will actually happen: the highest-probability
  // 1X2 outcome (~55% hit, on par with the market). Sourced from market_board.MS.
  const msBoard = prediction.market_board?.MS;
  const matchResultPrediction = (() => {
    const probs = msBoard?.probs;
    if (!probs) return null;
    const labelMap: Record<string, string> = {
      "1": prediction.match_info?.home_team || uiText("home", "Ev Sahibi"),
      X: uiText("draw", "Beraberlik"),
      "2": prediction.match_info?.away_team || uiText("away", "Deplasman"),
    };
    let bestKey = "";
    let bestProb = -1;
    for (const [k, v] of Object.entries(probs)) {
      const p = typeof v === "number" ? v : 0;
      if (p > bestProb) {
        bestProb = p;
        bestKey = k;
      }
    }
    if (!bestKey) return null;
    return {
      pick: bestKey,
      label: labelMap[bestKey] ?? bestKey,
      prob: bestProb,
      all: probs as Record<string, number>,
    };
  })();

  // ── En Güvenilir Okuma (akıllı market seçimi) ──────────────────────
  // Backtest: always-MS headline = %53 hit; picking the HIGHEST-confidence
  // market per match = %74 hit (DC / Üst1.5 / Üst3.5 etc.). The model's
  // probabilities are fine — the upgrade is *choosing which market to lead
  // with*. We surface the most reliable read (highest calibrated_confidence
  // across all bet_summary markets), so e.g. a match with an unclear winner
  // but a clear "Üst 2.5" leads with the goals call instead of a coin-flip MS.
  const mostReliableRead = (() => {
    const items = prediction.bet_summary;
    if (!Array.isArray(items) || items.length === 0) return null;
    let best: (typeof items)[number] | null = null;
    for (const it of items) {
      const conf = it.calibrated_confidence ?? 0;
      // require a genuinely confident read; skip near-coinflip
      if (conf < 55) continue;
      if (!best || conf > (best.calibrated_confidence ?? 0)) best = it;
    }
    if (!best) return null;
    return best;
  })();

  const sport = getPredictionSport(prediction);
  const isBasketball = sport === "basketball";

  const engineDetail = prediction.engine_breakdown.detail;
  const engineItems = [
    {
      key: "team",
      icon: LuGauge,
      label: isBasketball
        ? uiText("engine-team-basketball", "Takım Formu")
        : uiText("engine-team-football", "Takım Gücü"),
      value: prediction.engine_breakdown.team,
      color: "blue.400",
      detail: engineDetail?.team,
    },
    {
      key: "player",
      icon: LuSparkles,
      label: isBasketball
        ? uiText("engine-player-basketball", "Kadro Etkisi")
        : uiText("engine-player-football", "Oyuncu Etkisi"),
      value: prediction.engine_breakdown.player,
      color: "green.400",
      detail: engineDetail?.player,
    },
    {
      key: "odds",
      icon: LuTrendingUp,
      label: uiText("engine-odds", "Oran Analizi"),
      value: prediction.engine_breakdown.odds,
      color: "orange.400",
      detail: engineDetail?.odds,
    },
    {
      key: "referee",
      icon: LuShieldAlert,
      label: isBasketball
        ? uiText("engine-referee-basketball", "Yardımcı Sinyaller")
        : uiText("engine-referee-football", "Hakem Etkisi"),
      value: prediction.engine_breakdown.referee,
      color: "purple.400",
      detail: engineDetail?.referee,
    },
  ];

  const liveScoreHome = prediction.match_info?.current_score_home;
  const liveScoreAway = prediction.match_info?.current_score_away;
  const isLive = Boolean(prediction.match_info?.is_live);
  const isStale = Boolean(prediction.prediction_freshness?.is_stale_for_live);
  const contradictions = prediction.match_commentary?.contradictions || [];
  const pickCardLabels = {
    confidence: uiText("confidence-label", "Güven"),
    odds: uiText("odds-label", "Oran"),
    recommendedStake: uiText("stake-label-short", "Stake"),
    playScore: uiText("play-score-label", "Model Sinyali"),
    playability: uiText("playability-label", "Model sinyali"),
    confidenceInterval: uiText("confidence-interval", "Güven Aralığı"),
    confidenceBand: uiText("confidence-band", "Band"),
    confidenceIntervalWarning: uiText(
      "confidence-interval-warning",
      "Güven aralığı geniş. Sinyal olsa bile tek başına oynanması önerilmez.",
    ),
    theoreticalEdgeInline: uiText("theoretical-edge-inline", "Teorik avantaj"),
    modelProbability: uiText("model-probability-short", "Model"),
    marketProbability: uiText("market-probability-short", "Piyasa"),
  };

  const leagueConfidence = prediction.match_info?.league_confidence;
  const leagueConfStyles: Record<string, { color: string; label: string }> = {
    high: {
      color: "green",
      label: uiText("league-conf-high", "Bu ligde model güçlü"),
    },
    medium: {
      color: "yellow",
      label: uiText("league-conf-medium", "Bu ligde model orta"),
    },
    low: {
      color: "red",
      label: uiText("league-conf-low", "Bu ligde model zayıf"),
    },
  };
  const leagueConfMeta = leagueConfidence
    ? leagueConfStyles[leagueConfidence.label]
    : null;

  return (
    <VStack align="stretch" gap={5}>
      {leagueConfidence && leagueConfMeta ? (
        <HStack
          justify="space-between"
          p={2.5}
          px={3}
          borderWidth="1px"
          borderColor={`${leagueConfMeta.color}.300`}
          bg={`${leagueConfMeta.color}.50`}
          borderRadius="lg"
          _dark={{ bg: `${leagueConfMeta.color}.950` }}
          flexWrap="wrap"
          gap={2}
        >
          <HStack gap={2}>
            <Badge colorPalette={leagueConfMeta.color} variant="solid">
              {leagueConfMeta.label}
            </Badge>
            <Text fontSize="xs" color="fg.muted">
              {uiText("league-conf-basis", "geçmiş performans")}: ROI{" "}
              {leagueConfidence.bet_roi > 0 ? "+" : ""}
              {leagueConfidence.bet_roi}% · {leagueConfidence.bet_n}{" "}
              {uiText("bets-short", "bahis")}
            </Text>
          </HStack>
        </HStack>
      ) : null}
      {isLive ? (
        <Box
          p={3}
          bg={liveBg}
          borderWidth="1px"
          borderColor={liveBorderColor}
          borderRadius="xl"
        >
          <HStack justify="space-between" align="center">
            <HStack gap={2}>
              <Icon as={LuFlame} color="red.500" />
              <Text fontWeight="bold" color="red.600">
                🔴 {uiText("live", "CANLI")}
              </Text>
              {liveScoreHome != null && liveScoreAway != null ? (
                <Text fontWeight="semibold">
                  {prediction.match_info.home_team} {liveScoreHome} -{" "}
                  {liveScoreAway} {prediction.match_info.away_team}
                </Text>
              ) : null}
            </HStack>
            {isStale ? (
              <Badge colorPalette="orange" variant="solid">
                {uiText("pre-match-prediction", "Maç öncesi tahmin")}
              </Badge>
            ) : null}
          </HStack>
        </Box>
      ) : null}

      {contradictions.length ? (
        <Box
          p={3}
          bg={warningBg}
          borderWidth="1px"
          borderColor={warningBorderColor}
          borderRadius="xl"
        >
          <HStack align="start" gap={2}>
            <Icon as={LuTriangleAlert} color="yellow.600" mt={0.5} />
            <VStack align="start" gap={1}>
              <Text fontWeight="semibold">
                {uiText("prediction-contradictions", "Tahmin Çelişkileri")}
              </Text>
              {contradictions.map((text, idx) => (
                <Text key={idx} fontSize="sm" color="fg.muted">
                  • {text}
                </Text>
              ))}
            </VStack>
          </HStack>
        </Box>
      ) : null}

      <Card.Root bg={pageBg} borderColor={borderColor} borderRadius="2xl">
        <Card.Body gap={5}>
          <SectionTitle
            icon={LuBrain}
            title={uiText("summary-title", "Tahmin Özeti")}
            info={uiText(
              "summary-info",
              "Model sinyallerini ve belirsizlikleri sade şekilde gösterir.",
            )}
          />
          <Box
            p={3}
            bg={orangeBg}
            borderWidth="1px"
            borderColor={orangeBorderColor}
            borderRadius="xl"
          >
            <HStack align="start" gap={2}>
              <Icon
                as={LuShieldAlert}
                boxSize={4.5}
                color="orange.500"
                mt={0.5}
              />
              <Text fontSize="sm" color="fg.muted" lineHeight="tall">
                {uiText(
                  "model-signal-disclaimer",
                  "Bu bir model sinyalidir; kesin sonuç, garanti veya tutma yüzdesi değildir. Sinyal puanı maç içi varyans, kadro ve veri kalitesi nedeniyle yanılabilir.",
                )}
              </Text>
            </HStack>
          </Box>

          {matchResultPrediction ? (
            <Box
              p={5}
              bg={mrPredBg}
              borderWidth="2px"
              borderColor={mrPredBorder}
              borderRadius="2xl"
            >
              <HStack justify="space-between" align="start" mb={3}>
                <VStack align="start" gap={1}>
                  <Badge colorPalette="blue" variant="solid" borderRadius="full">
                    {uiText("match-result-prediction", "Maç Sonucu Tahmini")}
                  </Badge>
                  <Text fontSize="2xl" fontWeight="bold">
                    {matchResultPrediction.label}
                  </Text>
                  <Text fontSize="sm" color="fg.muted">
                    {uiText(
                      "match-result-copy",
                      "Modelin en olası gördüğü sonuç (kim kazanır).",
                    )}
                  </Text>
                </VStack>
                <VStack align="end" gap={0}>
                  <Text fontSize="2xl" fontWeight="bold" color="blue.500">
                    {formatPercent(matchResultPrediction.prob * 100, 0)}
                  </Text>
                  <Text fontSize="xs" color="fg.muted">
                    {uiText("probability-short", "olasılık")}
                  </Text>
                </VStack>
              </HStack>
              {/* 1X2 dağılımı */}
              <VStack align="stretch" gap={2}>
                {["1", "X", "2"].map((k) => {
                  const p = matchResultPrediction.all[k] ?? 0;
                  const lbl: Record<string, string> = {
                    "1":
                      prediction.match_info?.home_team ||
                      uiText("home", "Ev Sahibi"),
                    X: uiText("draw", "Beraberlik"),
                    "2":
                      prediction.match_info?.away_team ||
                      uiText("away", "Deplasman"),
                  };
                  const isTop = k === matchResultPrediction.pick;
                  return (
                    <Box key={k}>
                      <Flex justify="space-between" mb={1}>
                        <Text
                          fontSize="sm"
                          fontWeight={isTop ? "semibold" : "normal"}
                          color={isTop ? "blue.500" : "fg.muted"}
                        >
                          {lbl[k]}
                        </Text>
                        <Text fontSize="sm" fontWeight={isTop ? "semibold" : "normal"}>
                          {formatPercent(p * 100, 0)}
                        </Text>
                      </Flex>
                      <Bar
                        value={p * 100}
                        color={isTop ? "blue.400" : "gray.400"}
                        trackBg={trackBgColor}
                        height="6px"
                      />
                    </Box>
                  );
                })}
              </VStack>
              <Text fontSize="xs" color="fg.muted" mt={3}>
                {uiText(
                  "match-result-vs-value",
                  "Bu en olası sonuçtur. Aşağıdaki “Değerli Bahis” ise orana göre en kârlı görülen seçimdir — ikisi farklı olabilir.",
                )}
              </Text>
            </Box>
          ) : null}

          {mostReliableRead ? (
            <Box
              p={4}
              bg={statCardBg}
              borderWidth="1px"
              borderColor={borderColor}
              borderRadius="2xl"
            >
              <HStack justify="space-between" align="start" flexWrap="wrap" gap={2}>
                <VStack align="start" gap={1}>
                  <Badge colorPalette="teal" variant="subtle" borderRadius="full">
                    {uiText("most-reliable-read", "En Güvenilir Okuma")}
                  </Badge>
                  <HStack gap={2}>
                    <Text fontSize="xl" fontWeight="bold">
                      {getMarketLabel(mostReliableRead.market, marketLabels)}:{" "}
                      {mostReliableRead.pick}
                    </Text>
                  </HStack>
                  <Text fontSize="sm" color="fg.muted" maxW="440px">
                    {uiText(
                      "most-reliable-copy",
                      "Bu maçta modelin en yüksek isabetle okuduğu market. Maç sonucu belirsiz olsa bile bu okuma daha güçlü olabilir.",
                    )}
                  </Text>
                </VStack>
                <VStack align="end" gap={0}>
                  <Text fontSize="2xl" fontWeight="bold" color="teal.500">
                    {formatPercent(
                      mostReliableRead.unified_score ??
                        mostReliableRead.calibrated_confidence,
                      0,
                    )}
                  </Text>
                  <Text fontSize="xs" color="fg.muted">
                    {uiText("confidence-label", "Güven")}
                  </Text>
                </VStack>
              </HStack>
            </Box>
          ) : null}

          {recommendedPick ? (
            <Grid templateColumns={{ base: "1fr", xl: "1.4fr 1fr" }} gap={4}>
              <Box
                p={4}
                bg={greenBg}
                borderWidth="1px"
                borderColor={greenBorderColor}
                borderRadius="2xl"
              >
                <HStack justify="space-between" align="start" mb={4}>
                  <VStack align="start" gap={2}>
                    <Badge
                      colorPalette="green"
                      variant="solid"
                      borderRadius="full"
                    >
                      {uiText("main-recommendation", "Değerli Bahis")}
                    </Badge>
                    <Text fontSize="2xl" fontWeight="bold">
                      {recommendedPick.pick}
                    </Text>
                    <Text fontSize="xs" color="fg.muted" maxW="380px">
                      {uiText(
                        "value-bet-framing",
                        "Bu, maçın en olası sonucu DEĞİL — orana göre uzun vadede kârlı görülen değer bahsidir. Tek başına tutma olasılığı düşük olabilir.",
                      )}
                    </Text>
                    <Text fontSize="sm" color="fg.muted">
                      {getMarketLabel(recommendedPick.market, marketLabels)}{" "}
                      {uiText("best-market-copy", "marketinde en güçlü seçim.")}
                    </Text>
                    <HStack gap={2} flexWrap="wrap">
                      <Badge colorPalette={mainBandPalette} variant="subtle">
                        {getConfidenceBandLabel(
                          prediction.bet_advice.confidence_band,
                          ui,
                        )}
                      </Badge>
                      {recommendedPick.confidence_interval ? (
                        <Badge variant="outline">
                          {formatInterval(recommendedPick.confidence_interval)}
                        </Badge>
                      ) : null}
                    </HStack>
                  </VStack>
                  <Icon as={LuBadgeCheck} boxSize={8} color="green.500" />
                </HStack>
                <SimpleGrid columns={{ base: 2, md: 4 }} gap={3}>
                  <MetricTile
                    label={uiText("confidence-label", "Güven")}
                    value={formatPercent(
                      recommendedPick.unified_score ?? recommendedPick.calibrated_confidence,
                      0,
                    )}
                  />
                  <MetricTile
                    label={uiText("odds-label", "Oran")}
                    value={formatOdds(recommendedPick.odds)}
                  />
                  <MetricTile
                    label={uiText("confidence-interval", "Güven Aralığı")}
                    value={formatInterval(recommendedPick.confidence_interval)}
                  />
                  <MetricTile
                    label={uiText("edge-label", "Teorik Avantaj")}
                    value={formatEdgeSignal(recommendedPick.ev_edge)}
                    helper={uiText(
                      "edge-info",
                      "Model olasılığı ile piyasa olasılığı arasındaki teorik farktır; tutma garantisi veya kesin kazanç beklentisi değildir.",
                    )}
                    accent={`${getEdgePalette(recommendedPick.ev_edge)}.500`}
                  />
                  <MetricTile
                    label={uiText("stake-label", "Önerilen Miktar (Stake)")}
                    value={formatUnits(
                      recommendedPick.stake_units ||
                        prediction.bet_advice.suggested_stake_units,
                    )}
                    helper={uiText(
                      "stake-info",
                      "Stake, bu bahis için önerilen bahis birimidir. 2.0u, kendi bankroll planınızdaki 2 birimlik bahis anlamına gelir.",
                    )}
                  />
                </SimpleGrid>
              </Box>

              <Box
                p={4}
                bg={cardBg}
                borderWidth="1px"
                borderColor={borderColor}
                borderRadius="2xl"
              >
                <Text fontSize="sm" fontWeight="semibold" mb={3}>
                  {uiText("quick-read", "Hızlı yorum")}
                </Text>
                <ReasonList
                  items={[
                    ...prediction.reasoning_factors.slice(0, 2),
                    prediction.risk.surprise_type || "",
                  ].filter(Boolean)}
                  resolveReason={resolveReason}
                />
              </Box>
            </Grid>
          ) : null}

          <SimpleGrid columns={{ base: 1, md: 2, xl: 4 }} gap={3}>
            <MetricTile
              label={uiText("data-quality", "Veri Kalitesi")}
              value={formatPercent(prediction.data_quality.score * 100, 0)}
              helper={uiText(
                "data-quality-info",
                "Kadro, oran ve maç verisinin ne kadar güvenilir olduğu.",
              )}
              accent={`${qualityPalette}.500`}
            />
            <MetricTile
              label={t("risk-level")}
              value={`${prediction.risk.level} (${prediction.risk.score}/100)`}
              helper={uiText(
                "risk-info",
                "Sürpriz ihtimali ve belirsizlik seviyesi.",
              )}
              accent={`${riskPalette}.500`}
            />
            <MetricTile
              label={uiText("lineup-source", "Kadronun Kaynağı")}
              value={getLineupSourceLabel(
                prediction.data_quality.lineup_source,
                ui,
              )}
            />
            <MetricTile
              label={uiText("model-label", "Model")}
              value={prediction.model_version}
            />
          </SimpleGrid>

          {prediction.risk.is_surprise_risk ||
          prediction.risk.warnings?.length ? (
            <Box
              p={4}
              bg={orangeBg}
              borderWidth="1px"
              borderColor={orangeBorderColor}
              borderRadius="2xl"
            >
              <HStack align="start" gap={3}>
                <Icon
                  as={LuTriangleAlert}
                  boxSize={5}
                  color="orange.500"
                  mt={0.5}
                />
                <VStack align="start" gap={1.5}>
                  <Text fontWeight="semibold">
                    {uiText("risk-commentary", "Risk Yorumu")}
                  </Text>
                  <Text fontSize="sm" color="fg.muted">
                    {prediction.risk.surprise_comment ||
                      (prediction.risk.surprise_type
                        ? `${resolveReason(prediction.risk.surprise_type)}`
                        : uiText(
                            "risk-default-comment",
                            "Model bu maçta ekstra dikkat istiyor.",
                          ))}
                  </Text>
                  {prediction.risk.surprise_score !== undefined ? (
                    <Text
                      fontSize="sm"
                      fontWeight="semibold"
                      color="orange.600"
                    >
                      {uiText("surprise-score", "Sürpriz skoru")}:{" "}
                      {formatPercent(prediction.risk.surprise_score, 0)}
                    </Text>
                  ) : null}
                  {prediction.risk.surprise_breakdown?.length ? (
                    <VStack align="start" gap={1} mt={1}>
                      {prediction.risk.surprise_breakdown.map((entry) => (
                        <HStack key={entry.code} gap={2}>
                          <Badge
                            colorPalette={
                              entry.points >= 15
                                ? "red"
                                : entry.points >= 8
                                  ? "orange"
                                  : "yellow"
                            }
                            variant="subtle"
                          >
                            +{entry.points.toFixed(0)}
                          </Badge>
                          <Text fontSize="sm" color="fg.muted">
                            {entry.label}
                          </Text>
                        </HStack>
                      ))}
                    </VStack>
                  ) : (
                    <ReasonList
                      items={[
                        ...(prediction.risk.surprise_reasons || []),
                        ...prediction.risk.warnings,
                      ]}
                      resolveReason={resolveReason}
                    />
                  )}
                </VStack>
              </HStack>
            </Box>
          ) : null}
        </Card.Body>
      </Card.Root>

      <Card.Root bg={cardBg} borderColor={borderColor} borderRadius="2xl">
        <Card.Body gap={4}>
          <SectionTitle
            icon={LuChartColumn}
            title={t("engine-breakdown-title")}
            info={uiText(
              "engine-info",
              "Tahmini en çok hangi bileşenlerin etkilediğini gösterir.",
            )}
          />
          <SimpleGrid columns={{ base: 1, md: 2 }} gap={4}>
            {engineItems.map((item) => (
              <Box
                key={item.key}
                p={4}
                bg={statCardBg}
                borderWidth="1px"
                borderColor={borderColor}
                borderRadius="xl"
              >
                <HStack justify="space-between" mb={2}>
                  <HStack gap={2}>
                    <Icon as={item.icon} boxSize={4} color={item.color} />
                    <Text fontSize="sm" fontWeight="semibold">
                      {item.label}
                    </Text>
                  </HStack>
                  <HStack gap={2}>
                    {item.detail?.label ? (
                      <Badge
                        colorPalette={getEngineLabelPalette(item.detail.label)}
                        variant="subtle"
                      >
                        {getEngineLabelText(item.detail.label, ui)}
                      </Badge>
                    ) : null}
                    <Text fontSize="sm" fontWeight="bold">
                      +{item.value.toFixed(1)}
                    </Text>
                  </HStack>
                </HStack>
                <Bar
                  value={Math.min(item.value, 100)}
                  color={item.color}
                  trackBg={trackBgColor}
                />
                {item.detail?.interpretation ? (
                  <Text fontSize="xs" color="fg.muted" mt={2}>
                    {item.detail.interpretation}
                  </Text>
                ) : null}
              </Box>
            ))}
          </SimpleGrid>
        </Card.Body>
      </Card.Root>

      {recommendedPick ? (
        <PickCard
          pick={recommendedPick}
          title={uiText("best-single-pick", "En güçlü sinyal")}
          resolveReason={resolveReason}
          palette="green"
          stakeFallback={prediction.bet_advice.suggested_stake_units}
          marketLabels={marketLabels}
          labels={pickCardLabels}
          ui={ui}
        />
      ) : null}

      {prediction.supporting_picks?.length ? (
        <Card.Root bg={cardBg} borderColor={borderColor} borderRadius="2xl">
          <Card.Body gap={4}>
            <SectionTitle
              icon={LuFlame}
              title={uiText("alternative-markets", "Alternatif Marketler")}
              info={uiText(
                "alternative-markets-info",
                "Ana tahmin dışındaki seçenekler.",
              )}
            />
            <SimpleGrid columns={{ base: 1, xl: 2 }} gap={4}>
              {prediction.supporting_picks.map((pick) => (
                <PickCard
                  key={`${pick.market}-${pick.pick}`}
                  pick={pick}
                  title={
                    pick.playable
                      ? uiText("alternative", "Alternatif")
                      : uiText("pass-market", "Elenen Market")
                  }
                  resolveReason={resolveReason}
                  palette={pick.ev_edge > 0 ? "blue" : "orange"}
                  marketLabels={marketLabels}
                  labels={pickCardLabels}
                  ui={ui}
                />
              ))}
            </SimpleGrid>
          </Card.Body>
        </Card.Root>
      ) : null}

      <SummaryTable
        items={prediction.bet_summary || []}
        marketLabels={marketLabels}
        title={uiText("all-markets-title", "Tüm Marketler")}
        info={uiText(
          "all-markets-info",
          "Bütün seçenekleri tek tabloda karşılaştırır.",
        )}
        ui={ui}
      />
      {prediction.match_commentary?.headline ||
      prediction.match_commentary?.summary ? (
        <Card.Root bg={cardBg} borderColor={borderColor} borderRadius="2xl">
          <Card.Body gap={3}>
            <SectionTitle
              icon={LuBrain}
              title={uiText("match-commentary-title", "Maç Yorumu")}
              info={uiText(
                "match-commentary-info",
                "Modelin maç hakkındaki insan okunabilir özeti.",
              )}
            />
            {prediction.match_commentary.headline ? (
              <Text fontSize="md" fontWeight="bold">
                {prediction.match_commentary.headline}
              </Text>
            ) : null}
            {prediction.match_commentary.summary ? (
              <Text fontSize="sm" color="fg.muted">
                {prediction.match_commentary.summary}
              </Text>
            ) : null}
            {prediction.match_commentary.notes?.length ? (
              <VStack align="start" gap={1}>
                {prediction.match_commentary.notes.map((note, idx) => (
                  <Text key={idx} fontSize="sm">
                    • {note}
                  </Text>
                ))}
              </VStack>
            ) : null}
          </Card.Body>
        </Card.Root>
      ) : null}
      <ScoreCard prediction={prediction} sport={sport} ui={ui} />
      <MarketBoardSection
        marketBoard={prediction.market_board}
        betSummary={prediction.bet_summary || []}
        marketLabels={marketLabels}
        title={t("market-board")}
        info={uiText(
          "market-board-info",
          "Modelin her markette gördüğü olasılık dağılımı.",
        )}
        ui={ui}
      />

      {prediction.v27_engine ? (
        <V28OddsBandPanel engine={prediction.v27_engine as V27EngineDto} />
      ) : null}

      <Card.Root bg={cardBg} borderColor={borderColor} borderRadius="2xl">
        <Card.Body gap={4}>
          <SectionTitle
            icon={LuSparkles}
            title={t("bet-advice")}
            info={uiText("bet-advice-info", "Modelin nihai aksiyon önerisi.")}
          />
          <HStack
            justify="space-between"
            align={{ base: "start", md: "center" }}
            flexDir={{ base: "column", md: "row" }}
            gap={3}
          >
            <HStack gap={3}>
              <Badge
                colorPalette={prediction.bet_advice.playable ? "green" : "red"}
                variant="solid"
                borderRadius="full"
                fontSize="sm"
                px={3}
                py={1}
              >
                {prediction.bet_advice.playable
                  ? uiText("bet-advice-play", "OYNA")
                  : uiText("bet-advice-pass", "OYNAMA")}
              </Badge>
              <Badge
                colorPalette={mainBandPalette}
                variant="subtle"
                borderRadius="full"
                fontSize="sm"
                px={3}
                py={1}
              >
                {getConfidenceBandLabel(
                  prediction.bet_advice.confidence_band,
                  ui,
                )}
              </Badge>
              <Badge
                colorPalette={getSignalTierPalette(
                  prediction.bet_advice.signal_tier,
                )}
                variant="subtle"
                borderRadius="full"
                fontSize="sm"
                px={3}
                py={1}
              >
                {getSignalTierLabel(prediction.bet_advice.signal_tier, ui)}
              </Badge>
              <Text color="fg.muted">
                {resolveReason(prediction.bet_advice.reason)}
              </Text>
            </HStack>
            <Badge variant="surface" fontSize="sm" px={3} py={1}>
              {uiText("recommended-stake-inline", "Önerilen miktar")}:{" "}
              {formatUnits(prediction.bet_advice.suggested_stake_units)}
            </Badge>
          </HStack>
          <Separator />
          <SectionTitle
            icon={LuBrain}
            title={t("reasoning")}
            info={uiText(
              "reasoning-info",
              "Modelin bu maçı neden bu şekilde okuduğunun üst seviye özeti.",
            )}
          />
          <ReasonList
            items={prediction.reasoning_factors}
            resolveReason={resolveReason}
          />
        </Card.Body>
      </Card.Root>
    </VStack>
  );
}
