<template>
    <view class="worldcup-page">
        <view class="worldcup-header" :style="{ paddingTop: statusBarHeight + 'px' }">
            <view class="worldcup-header__bar">
                <view class="worldcup-header__back" @tap="goBack">
                    <u-icon name="arrow-left" size="38" color="#ffffff"></u-icon>
                </view>
                <view class="worldcup-header__switch" @tap="goBack">
                    <text>其他赛事</text>
                </view>
            </view>

            <view class="worldcup-header__hero">
                <text class="worldcup-header__watermark">2</text>
                <view class="worldcup-header__badge">
                    <text class="worldcup-header__badge-cup">🏆</text>
                    <text class="worldcup-header__badge-label">FIFA</text>
                </view>
                <text class="worldcup-header__title">2026年美加墨世界杯</text>
            </view>

            <scroll-view scroll-x class="worldcup-nav" show-scrollbar="false">
                <view class="worldcup-nav__inner">
                    <view v-for="tab in tabs" :key="tab.key" class="worldcup-nav__item"
                        :class="{ 'worldcup-nav__item--active': activeTab === tab.key }" @tap="switchTab(tab.key)">
                        <text>{{ tab.label }}</text>
                    </view>
                </view>
            </scroll-view>
        </view>

        <scroll-view scroll-y scroll-with-animation class="worldcup-scroll"
            :scroll-into-view="activeTab === 'schedule' ? scheduleScrollIntoView : ''">
            <block v-if="activeTab === 'live'">
                <view v-if="liveCards.length" class="worldcup-live-grid">
                    <view v-for="live in liveCards" :key="`live-${live.live_id}`" class="worldcup-live-card"
                        @tap="openWorldCupLiveCard(live)">
                        <view class="worldcup-live-card__player-wrap"
                            :class="{ 'worldcup-live-card__player-wrap--poster': useLiveCardPosterMode }">
                            <video v-if="!useLiveCardPosterMode" :id="buildWorldCupLiveVideoId(live)"
                                class="worldcup-live-card__player" :src="resolveWorldCupLivePlayUrl(live)"
                                :poster="live.home_icon || live.away_icon || ''" :autoplay="true" :muted="true"
                                :controls="!hideLiveCardControlsOnAndroid"
                                :show-play-btn="!hideLiveCardControlsOnAndroid"
                                :show-fullscreen-btn="!hideLiveCardControlsOnAndroid" object-fit="cover" />
                            <view v-else class="worldcup-live-card__poster">
                                <image v-if="resolveWorldCupLivePoster(live)" class="worldcup-live-card__poster-image"
                                    :src="resolveWorldCupLivePoster(live)" mode="aspectFill" />
                                <view v-else class="worldcup-live-card__poster-empty">
                                    <text>{{ livePosterTitle(live) }}</text>
                                </view>
                                <view class="worldcup-live-card__poster-shade"></view>
                                <view class="worldcup-live-card__play">
                                    <view class="worldcup-live-card__play-icon"></view>
                                </view>
                                <text class="worldcup-live-card__status">{{ liveStatusText(live) }}</text>
                            </view>
                        </view>

                        <view class="worldcup-live-card__teams">
                            <text class="worldcup-live-card__line">{{ liveLineTitle(live) }}</text>
                        </view>

                        <view class="worldcup-live-card__meta">
                            <view class="worldcup-live-card__anchor">
                                <image v-if="liveAnchorAvatar(live)" class="worldcup-live-card__avatar"
                                    :src="liveAnchorAvatar(live)" mode="aspectFill" />
                                <view v-else class="worldcup-live-card__avatar worldcup-live-card__avatar--empty">
                                    <text>主</text>
                                </view>
                                <text class="worldcup-live-card__anchor-name">{{ liveAnchorName(live) }}</text>
                            </view>
                            <view class="worldcup-live-card__stats">
                                <text class="worldcup-live-card__stat">观看 {{ formatLiveCount(live.room_view_count)
                                    }}</text>
                                <text class="worldcup-live-card__stat">关注 {{ formatLiveCount(live.room_focus_count)
                                    }}</text>
                            </view>
                            <text class="worldcup-live-card__notice">{{ liveRoomNotice(live) }}</text>
                        </view>

                    </view>
                </view>
                <view v-else class="worldcup-empty">
                    <u-empty text="暂无直播" mode="data" />
                </view>
            </block>

            <block v-else-if="activeTab === 'schedule'">
                <view class="worldcup-sortbar" @tap="toggleScheduleSort">
                    <text class="worldcup-sortbar__label">{{ scheduleSortLabel }}</text>
                    <text class="worldcup-sortbar__icon">↕</text>
                </view>

                <block v-if="scheduleGroups.length">
                    <view v-for="group in scheduleGroups" :key="group.key" :id="scheduleGroupAnchorId(group.key)"
                        class="worldcup-group">
                        <view class="worldcup-group__title">
                            <view class="worldcup-group__dot"></view>
                            <text>{{ group.label }}</text>
                        </view>

                        <view v-for="(match, index) in group.items" :key="match.id || match.match_id"
                            class="wc-match-card" @tap="goMatchDetail(match)">
                            <view class="wc-match-card__team wc-match-card__team--left">
                                <image v-if="match.home_icon" class="wc-match-card__logo" :src="match.home_icon"
                                    mode="aspectFit" />
                                <text class="wc-match-card__team-name">{{ match.home_team }}</text>
                            </view>

                            <view class="wc-match-card__center">
                                <text class="wc-match-card__time">{{ matchCenterText(match) }}</text>
                                <text class="wc-match-card__meta">{{ matchMetaText(match, index) }}</text>
                            </view>

                            <view class="wc-match-card__team wc-match-card__team--right">
                                <image v-if="match.away_icon" class="wc-match-card__logo" :src="match.away_icon"
                                    mode="aspectFit" />
                                <text class="wc-match-card__team-name">{{ match.away_team }}</text>
                            </view>
                        </view>
                    </view>
                </block>
                <view v-else class="worldcup-empty">
                    <u-empty text="暂无数据" mode="data" />
                </view>
            </block>

            <block v-else-if="activeTab === 'odds'">
                <view class="worldcup-odds-filter">
                    <scroll-view scroll-x class="worldcup-odds-filter__tabs" show-scrollbar="false">
                        <view class="worldcup-odds-filter__tabs-inner">
                            <view v-for="item in oddsShowTypeOptions" :key="item.key" class="worldcup-odds-filter__tab"
                                :class="{ 'worldcup-odds-filter__tab--active': oddsShowType === item.key }"
                                @tap="switchOddsShowType(item.key)">
                                <text>{{ item.label }}</text>
                            </view>
                        </view>
                    </scroll-view>

                    <view class="worldcup-odds-filter__search">
                        <u-icon name="search" size="30" color="#94a3b8"></u-icon>
                        <input v-model="oddsSearchText" class="worldcup-odds-filter__input" confirm-type="search"
                            placeholder="搜索联赛/球队" placeholder-class="worldcup-odds-filter__placeholder"
                            @confirm="confirmOddsSearch" />
                        <view v-if="oddsSearchText || oddsKeyword" class="worldcup-odds-filter__clear"
                            @tap="clearOddsKeyword">
                            <u-icon name="close" size="24" color="#94a3b8"></u-icon>
                        </view>
                        <view class="worldcup-odds-filter__button" @tap="confirmOddsSearch">
                            <text>筛选</text>
                        </view>
                    </view>

                    <view class="worldcup-odds-filter__meta">
                        <text>{{ oddsFilterSummary }}</text>
                    </view>
                </view>

                <view v-if="oddsLoading" class="worldcup-loading">
                    <u-loading mode="circle" />
                    <text>加载中...</text>
                </view>

                <block v-else-if="oddsList.length">
                    <view v-for="match in oddsList" :key="oddsMatchKey(match)" class="worldcup-odds-card"
                        @tap="goOddsMatchDetail(match)">
                        <view class="worldcup-odds-card__head">
                            <text class="worldcup-odds-card__league">{{ match.league_name || '赛事赔率' }}</text>
                            <text class="worldcup-odds-card__time">{{ oddsTimeText(match) }}</text>
                        </view>

                        <view class="worldcup-odds-card__teams">
                            <view class="worldcup-odds-card__team">
                                <image v-if="match.home_icon" class="worldcup-odds-card__logo"
                                    :src="match.home_icon" mode="aspectFit" />
                                <text class="worldcup-odds-card__team-name">{{ match.home_team }}</text>
                            </view>
                            <view class="worldcup-odds-card__vs">
                                <text>{{ oddsCenterText(match) }}</text>
                            </view>
                            <view class="worldcup-odds-card__team worldcup-odds-card__team--right">
                                <image v-if="match.away_icon" class="worldcup-odds-card__logo"
                                    :src="match.away_icon" mode="aspectFit" />
                                <text class="worldcup-odds-card__team-name">{{ match.away_team }}</text>
                            </view>
                        </view>

                        <view class="worldcup-odds-platform" v-for="platform in match.platforms"
                            :key="`${oddsMatchKey(match)}-${platform.platform_key}-${platform.source_match_id}`">
                            <view class="worldcup-odds-platform__head">
                                <view class="worldcup-odds-platform__name">
                                    <text>{{ platform.platform_name }}</text>
                                    <text class="worldcup-odds-platform__tag">{{ platform.show_type_text }}</text>
                                </view>
                                <text class="worldcup-odds-platform__update">{{ formatOddsUpdateTime(platform.update_time)
                                    }}</text>
                            </view>

                            <view class="worldcup-odds-market" v-for="market in platform.markets"
                                :key="`${platform.source_match_id}-${market.label}`">
                                <view class="worldcup-odds-market__title">
                                    <text>{{ market.label }}</text>
                                    <text v-if="market.line" class="worldcup-odds-market__line">{{ market.line }}</text>
                                </view>
                                <view class="worldcup-odds-market__values">
                                    <view class="worldcup-odds-value" v-for="item in market.values"
                                        :key="`${market.label}-${item.label}`">
                                        <text class="worldcup-odds-value__label">{{ item.label }}</text>
                                        <text class="worldcup-odds-value__number">{{ item.value }}</text>
                                    </view>
                                </view>
                            </view>
                        </view>
                    </view>
                </block>

                <view v-else class="worldcup-empty">
                    <u-empty text="暂无赔率" mode="data" />
                </view>
            </block>

            <view v-else-if="activeTab === 'rank'" class="worldcup-section">
                <ranking-nav v-model="rankingMode" />

                <view v-if="rankingMode === 'standings'">
                    <standings-panel :groups="standingData.groups" />
                </view>

                <view v-else>
                    <player-ranking-panel :title="currentRankingLabel" :header="currentRankingHeader"
                        :list="currentRankingList" />
                </view>
            </view>

            <view v-else-if="activeTab === 'bracket'" class="worldcup-section">
                <scroll-view scroll-x class="bracket-round-nav" show-scrollbar="false">
                    <view class="bracket-round-nav__inner">
                        <view v-for="tab in bracketTabs" :key="tab.key" class="bracket-round-nav__item"
                            :class="{ 'bracket-round-nav__item--active': activeBracketTab === tab.key }"
                            @tap="switchBracketTab(tab.key)">
                            <text>{{ tab.label }}</text>
                        </view>
                    </view>
                </scroll-view>

                <view v-if="activeBracketRound || activeBracketTab === '决赛'" class="bracket-stage">
                    <view v-if="activeBracketRound?.matches?.length" class="bracket-stage__list">
                        <view v-for="(pair, pairIndex) in activeBracketPairs" :key="`pair-${pairIndex}`"
                            class="bracket-stage__pair">
                            <view class="bracket-stage__cards">
                                <view v-for="match in pair" :key="match.match_id" class="bracket-stage__item">
                                    <view class="bracket-stage__card" @tap="goMatchDetail(match)">
                                        <view class="bracket-stage__time">
                                            <text class="bracket-stage__clock">{{ formatMatchTime(match.match_time)
                                            }}</text>
                                            <text class="bracket-stage__date">{{ formatBracketDate(match.match_time)
                                            }}</text>
                                        </view>
                                        <view class="bracket-stage__divider"></view>
                                        <view class="bracket-stage__teams">
                                            <view class="bracket-stage__team">
                                                <image v-if="resolveBracketTeamIcon(match.home_team, match.home_icon)"
                                                    class="bracket-stage__logo"
                                                    :src="resolveBracketTeamIcon(match.home_team, match.home_icon)"
                                                    mode="aspectFit" />
                                                <text class="bracket-stage__name"
                                                    :class="{ 'bracket-stage__name--multi': isBracketTeamGroup(match.home_team) }">{{
                                                        resolveBracketTeamName(match.home_team) }}</text>
                                            </view>
                                            <view class="bracket-stage__team">
                                                <image v-if="resolveBracketTeamIcon(match.away_team, match.away_icon)"
                                                    class="bracket-stage__logo"
                                                    :src="resolveBracketTeamIcon(match.away_team, match.away_icon)"
                                                    mode="aspectFit" />
                                                <text class="bracket-stage__name"
                                                    :class="{ 'bracket-stage__name--multi': isBracketTeamGroup(match.away_team) }">{{
                                                        resolveBracketTeamName(match.away_team) }}</text>
                                            </view>
                                        </view>
                                    </view>
                                </view>
                            </view>
                            <view v-if="activeBracketTab !== '决赛'" class="bracket-stage__linezone"></view>
                        </view>
                    </view>

                    <view v-if="activeBracketTab === '决赛' && thirdPlaceRound?.matches?.length" class="bracket-extra">
                        <text class="bracket-extra__title">三四名决赛</text>
                        <view class="bracket-stage__list bracket-stage__list--final">
                            <view v-for="match in thirdPlaceRound.matches" :key="match.match_id"
                                class="bracket-stage__item">
                                <view class="bracket-stage__card" @tap="goMatchDetail(match)">
                                    <view class="bracket-stage__time">
                                        <text class="bracket-stage__clock">{{ formatMatchTime(match.match_time)
                                        }}</text>
                                        <text class="bracket-stage__date">{{ formatBracketDate(match.match_time)
                                        }}</text>
                                    </view>
                                    <view class="bracket-stage__divider"></view>
                                    <view class="bracket-stage__teams">
                                        <view class="bracket-stage__team">
                                            <image v-if="resolveBracketTeamIcon(match.home_team, match.home_icon)"
                                                class="bracket-stage__logo"
                                                :src="resolveBracketTeamIcon(match.home_team, match.home_icon)"
                                                mode="aspectFit" />
                                            <text class="bracket-stage__name"
                                                :class="{ 'bracket-stage__name--multi': isBracketTeamGroup(match.home_team) }">{{
                                                    resolveBracketTeamName(match.home_team) }}</text>
                                        </view>
                                        <view class="bracket-stage__team">
                                            <image v-if="resolveBracketTeamIcon(match.away_team, match.away_icon)"
                                                class="bracket-stage__logo"
                                                :src="resolveBracketTeamIcon(match.away_team, match.away_icon)"
                                                mode="aspectFit" />
                                            <text class="bracket-stage__name"
                                                :class="{ 'bracket-stage__name--multi': isBracketTeamGroup(match.away_team) }">{{
                                                    resolveBracketTeamName(match.away_team) }}</text>
                                        </view>
                                    </view>
                                </view>
                            </view>
                        </view>
                    </view>
                </view>
                <view v-else class="worldcup-empty">
                    <u-empty text="暂无数据" mode="data" />
                </view>
            </view>

            <view v-else class="worldcup-section">
                <view v-if="newsLoading" class="worldcup-loading">
                    <u-loading mode="circle" />
                    <text>加载中...</text>
                </view>
                <view v-else-if="newsList.length">
                    <TranslatedArticleCard v-for="item in newsList" :key="item.id" :item="item" variant="worldcup"
                        author-fallback="Sport Era Editorial" />
                </view>
                <view v-else class="worldcup-empty">
                    <u-empty text="暂无数据" mode="data" />
                </view>
            </view>
        </scroll-view>
    </view>
</template>

<script setup lang="ts">
import { computed, nextTick, onMounted, ref, watch } from 'vue'
import RankingNav from '../pages/worldcup/components/ranking/RankingNav.vue'
import StandingsPanel from '../pages/worldcup/components/ranking/StandingsPanel.vue'
import PlayerRankingPanel from '../pages/worldcup/components/ranking/PlayerRankingPanel.vue'
import TranslatedArticleCard from '@/components/translated-article-card/translated-article-card.vue'
import { getArticleCate, getArticleList } from '@/api/news'
import {
    getWorldCupLiveCards,
    getWorldCupOdds,
    getWorldCupRankings,
    getWorldCupSchedule,
    getWorldCupStandings,
    type WorldCupLiveCardItem,
    type WorldCupOddsMatchItem,
} from '@/api/match'
import { getLocalMatchDate } from '@/utils/match-time'

type MainTab = 'live' | 'schedule' | 'odds' | 'rank' | 'bracket' | 'news'
type RankingMode = 'standings' | 'goals' | 'assists'
type ScheduleSort = 'time' | 'group'
type BracketTabKey = '1/16决赛' | '1/8决赛' | '1/4决赛' | '半决赛' | '决赛'
type OddsShowType = '' | 'live' | 'today' | 'early'

const props = withDefaults(defineProps<{
    initialTab?: string
    initialCid?: number | null
}>(), {
    initialTab: 'live',
    initialCid: null
})

const emit = defineEmits<{
    (e: 'back'): void
}>()

const showStandaloneOddsTab = false

const allTabs: { key: MainTab; label: string }[] = [
    { key: 'live', label: '直播' },
    { key: 'schedule', label: '比分和赛程' },
    { key: 'odds', label: '赔率' },
    { key: 'rank', label: '排名' },
    { key: 'bracket', label: '对阵图' },
    { key: 'news', label: '新闻' }
]
const tabs = allTabs.filter((item) => showStandaloneOddsTab || item.key !== 'odds')

const oddsShowTypeOptions: { key: OddsShowType; label: string }[] = [
    { key: '', label: '全部盘口' },
    { key: 'live', label: '滚球盘' },
    { key: 'today', label: '今日盘' },
    { key: 'early', label: '早盘' }
]

const WORLD_CUP_MATCH_CONTEXT = { competition_id: 61, league_name: '世界杯' }

const bracketTabs: { key: BracketTabKey; label: string }[] = [
    { key: '1/16决赛', label: '32强' },
    { key: '1/8决赛', label: '十六强' },
    { key: '1/4决赛', label: '四分之一决赛' },
    { key: '半决赛', label: '半决赛' },
    { key: '决赛', label: '决赛' }
]

const activeTab = ref<MainTab>('live')
const rankingMode = ref<RankingMode>('standings')
const scheduleSort = ref<ScheduleSort>('time')
const activeBracketTab = ref<BracketTabKey>(bracketTabs[0].key)
const scheduleScrollIntoView = ref('')
const statusBarHeight = ref(0)
const hideLiveCardControlsOnAndroid = ref(false)
const useLiveCardPosterMode = ref(false)
const liveCards = ref<WorldCupLiveCardItem[]>([])
const liveCardsLoaded = ref(false)
const oddsList = ref<WorldCupOddsMatchItem[]>([])
const oddsLoading = ref(false)
const oddsLoaded = ref(false)
const oddsShowType = ref<OddsShowType>('')
const oddsKeyword = ref('')
const oddsSearchText = ref('')
const oddsRequestSeq = ref(0)

const scheduleData = ref<any>({
    current_round_name: '',
    bracket_rounds: [],
    schedule_rounds: []
})

const standingData = ref<any>({
    stage_name: '',
    groups: []
})

const rankingData = ref<Record<RankingMode, any[]>>({
    standings: [],
    goals: [],
    assists: []
})

const rankingLoaded = ref<Record<RankingMode, boolean>>({
    standings: false,
    goals: false,
    assists: false
})

const newsCategoryId = ref<number | null>(null)
const newsList = ref<any[]>([])
const newsLoading = ref(false)
const newsLoaded = ref(false)

const resolveNewsCategoryId = async (cid?: string | number | null) => {
    const parsedCid = Number(cid || 0)
    if (parsedCid > 0) {
        newsCategoryId.value = parsedCid
        return newsCategoryId.value
    }

    if (newsCategoryId.value) return newsCategoryId.value

    const cateList = await getArticleCate()
    const cate = (cateList || []).find((item: any) => {
        const name = item?.name || item?.label || item?.title
        return String(name) === '世界杯'
    })
    newsCategoryId.value = cate?.id || null
    return newsCategoryId.value
}

const currentRankingHeader = computed(() => {
    if (rankingMode.value === 'goals') return ['球员', '球队', '进球']
    if (rankingMode.value === 'assists') return ['球员', '球队', '助攻']
    return ['球员', '球队', '积分']
})

const currentRankingLabel = computed(() => {
    if (rankingMode.value === 'goals') return '射手排名'
    if (rankingMode.value === 'assists') return '助攻排名'
    return '积分排名'
})

const currentRankingList = computed(() => {
    if (rankingMode.value === 'goals') return rankingData.value.goals
    if (rankingMode.value === 'assists') return rankingData.value.assists
    return rankingData.value.standings
})

const oddsFilterSummary = computed(() => {
    const showTypeLabel = oddsShowTypeOptions.find((item) => item.key === oddsShowType.value)?.label || '全部盘口'
    const keyword = oddsKeyword.value.trim()
    const parts = [showTypeLabel]
    if (keyword) parts.push(`"${keyword}"`)
    parts.push(`${oddsList.value.length}场`)
    return parts.join(' · ')
})

const groupRankTeamMap = computed(() => {
    const map = new Map<string, { name: string; logo: string }>()
        ; (standingData.value.groups || []).forEach((group: any) => {
            const groupKey = String(group?.group_name || '').match(/([A-L])/i)?.[1]?.toUpperCase()
            if (!groupKey) return

                ; (group?.teams || []).forEach((team: any, index: number) => {
                    const rank = Number(team?.rank || team?.row_order || index + 1)
                    if (!rank) return
                    map.set(`${groupKey}${rank}`, {
                        name: team?.team_name || '',
                        logo: team?.team_logo || ''
                    })
                })
        })
    return map
})

const canResolveBracketTeams = computed(() => {
    const currentRoundName = String(scheduleData.value.current_round_name || '')
    if (currentRoundName && !currentRoundName.includes('小组赛')) {
        return true
    }

    const groups = standingData.value.groups || []
    if (!groups.length) return false

    return groups.every((group: any) =>
        (group?.teams || []).every((team: any) => Number(team?.played || 0) >= 3)
    )
})

const bracketRankTokenPattern = /^[A-L](?:[1-4])$/i
const bracketRankGroupPattern = /^[A-L](?:[1-4])(?:\/[A-L](?:[1-4]))+$/i

const resolveBracketRankEntry = (rawValue: any) => {
    const value = String(rawValue || '').trim().toUpperCase()
    if (!canResolveBracketTeams.value) return null
    if (!value || !bracketRankTokenPattern.test(value)) return null
    return groupRankTeamMap.value.get(value) || null
}

const isBracketTeamGroup = (rawValue: any) => {
    return bracketRankGroupPattern.test(String(rawValue || '').trim().toUpperCase())
}

const resolveBracketTeamName = (rawValue: any) => {
    const raw = String(rawValue || '').trim()
    if (!raw) return ''

    const exact = resolveBracketRankEntry(raw)
    if (exact?.name) return exact.name

    if (isBracketTeamGroup(raw)) {
        return raw
            .split('/')
            .map((token) => resolveBracketRankEntry(token)?.name || token.trim())
            .join('/')
    }

    return raw
}

const resolveBracketTeamIcon = (rawValue: any, fallback = '') => {
    const raw = String(rawValue || '').trim()
    const exact = resolveBracketRankEntry(rawValue)
    if (exact?.logo) return exact.logo
    if (bracketRankTokenPattern.test(raw) || isBracketTeamGroup(raw) || /^第\d+场/.test(raw)) return ''
    return fallback
}

const normalizeLiveText = (value: unknown) => String(value || '').trim()

const liveLineTitle = (live: WorldCupLiveCardItem) => {
    return normalizeLiveText(live.title) || '直播线路'
}

const liveAnchorAvatar = (live: WorldCupLiveCardItem) => {
    return normalizeLiveText(live.anchor_avatar)
}

const liveAnchorName = (live: WorldCupLiveCardItem) => {
    return normalizeLiveText(live.anchor_name) || '主播'
}

const liveRoomNotice = (live: WorldCupLiveCardItem) => {
    return normalizeLiveText(live.room_notice) || '暂无公告'
}

const resolveWorldCupLivePoster = (live: WorldCupLiveCardItem) => {
    return liveAnchorAvatar(live) || normalizeLiveText(live.home_icon) || normalizeLiveText(live.away_icon)
}

const livePosterTitle = (live: WorldCupLiveCardItem) => {
    const teams = [normalizeLiveText(live.home_team), normalizeLiveText(live.away_team)].filter(Boolean)
    return teams.length ? teams.join(' VS ') : liveLineTitle(live)
}

const formatLiveCount = (value: unknown) => {
    const count = Number(value || 0)
    if (!Number.isFinite(count) || count <= 0) return '0'
    if (count >= 10000) {
        return `${(count / 10000).toFixed(count >= 100000 ? 0 : 1).replace(/\.0$/, '')}万`
    }
    return String(Math.floor(count))
}

const buildWorldCupLiveVideoId = (live: WorldCupLiveCardItem) => {
    return `worldcup-live-${live.live_id || live.id || 0}`
}

const resolveWorldCupLivePlayUrl = (live: WorldCupLiveCardItem) => {
    const urls: string[] = [
        live.play_url,
        live.default_play_url,
    ].map(normalizeLiveText).filter(Boolean)

    if (Array.isArray(live.stream_options)) {
        live.stream_options.forEach((option) => {
            urls.push(
                normalizeLiveText(option?.url),
                normalizeLiveText(option?.play_url),
                normalizeLiveText(option?.play_url_m3u8),
                normalizeLiveText(option?.play_url_hd_m3u8),
                normalizeLiveText(option?.play_url_flv),
                normalizeLiveText(option?.play_url_hd_flv)
            )
        })
    }

    return urls.find((url) => /\.(m3u8|mp4|flv)(\?|$)/i.test(url)) || urls[0] || ''
}

const resolveWorldCupLiveSourceUrl = (live: WorldCupLiveCardItem) => {
    return normalizeLiveText(live.source_url) || resolveWorldCupLivePlayUrl(live)
}

const liveStatusText = (live: WorldCupLiveCardItem) => {
    if ((live.status ?? 0) === 1) {
        return normalizeLiveText(live.current_minute) || '进行中'
    }
    return '未开赛'
}

const flattenScheduleMatches = computed(() => {
    const matches: any[] = []
        ; (scheduleData.value.schedule_rounds || []).forEach((round: any) => {
            ; (round.matches || []).forEach((match: any, index: number) => {
                matches.push({
                    ...match,
                    round_name: round.round_name,
                    round_index: index + 1
                })
            })
        })
    return matches.sort((a, b) => (a.match_time || 0) - (b.match_time || 0))
})

const scheduleGroups = computed(() => {
    const groups: Array<{ key: string; label: string; items: any[] }> = []

    if (scheduleSort.value === 'time') {
        const map = new Map<string, any[]>()
        flattenScheduleMatches.value.forEach((match) => {
            const key = formatDateKey(match.match_time)
            if (!map.has(key)) map.set(key, [])
            map.get(key)!.push(match)
        })
        map.forEach((items, key) => {
            groups.push({
                key,
                label: items[0] ? formatDateLabel(items[0].match_time) : '未分组',
                items
            })
        })
    } else {
        const map = new Map<string, any[]>()
        flattenScheduleMatches.value.forEach((match) => {
            const key = normalizeGroupName(match.stage || match.round_name)
            if (!map.has(key)) map.set(key, [])
            map.get(key)!.push(match)
        })
        map.forEach((items, key) => {
            groups.push({ key, label: key, items })
        })
    }

    return groups
})

const scheduleSortLabel = computed(() => scheduleSort.value === 'time' ? '时间排序' : '小组排序')

const activeBracketRound = computed(() => {
    return (scheduleData.value.bracket_rounds || []).find((item: any) => item.round_name === activeBracketTab.value) || null
})

const thirdPlaceRound = computed(() => {
    return (scheduleData.value.bracket_rounds || []).find((item: any) => item.round_name === '季军赛') || null
})

const activeBracketPairs = computed(() => {
    const matches = activeBracketRound.value?.matches || []
    const pairs: any[][] = []
    for (let i = 0; i < matches.length; i += 2) {
        pairs.push(matches.slice(i, i + 2))
    }
    return pairs
})

const initLayout = () => {
    const info = uni.getSystemInfoSync()
    const isAndroidPlatform = String(info.platform || '').toLowerCase() === 'android'
    hideLiveCardControlsOnAndroid.value = isAndroidPlatform
    useLiveCardPosterMode.value = false
    // #ifdef APP-PLUS
    useLiveCardPosterMode.value = isAndroidPlatform
    // #endif
    // #ifdef APP-PLUS || MP
    statusBarHeight.value = info.statusBarHeight || 44
    // #endif
    // #ifdef H5
    statusBarHeight.value = 0
    // #endif
}

const scheduleGroupAnchorId = (key: string) => `worldcup-schedule-group-${key}`

const fetchWorldCupLiveCards = async () => {
    if (liveCardsLoaded.value) return
    const data = await getWorldCupLiveCards()
    liveCards.value = Array.isArray(data?.list) ? data.list : []
    liveCardsLoaded.value = true
}

const fetchSchedule = async () => {
    scheduleData.value = await getWorldCupSchedule() || { current_round_name: '', bracket_rounds: [], schedule_rounds: [] }
    if (activeTab.value === 'schedule') {
        void scrollScheduleToToday()
    }
}

const buildOddsRequestParams = () => {
    const params: {
        show_type?: 'live' | 'today' | 'early'
        keyword?: string
        include_special: number
        limit: number
    } = {
        include_special: 0,
        limit: 300
    }
    if (oddsShowType.value) {
        params.show_type = oddsShowType.value
    }
    const keyword = oddsKeyword.value.trim()
    if (keyword) {
        params.keyword = keyword
    }
    return params
}

const fetchOdds = async (force = false) => {
    if (!force && (oddsLoaded.value || oddsLoading.value)) return
    const requestSeq = oddsRequestSeq.value + 1
    oddsRequestSeq.value = requestSeq
    oddsLoading.value = true
    try {
        const data = await getWorldCupOdds(buildOddsRequestParams())
        if (requestSeq === oddsRequestSeq.value) {
            oddsList.value = Array.isArray(data?.list) ? data.list : []
            oddsLoaded.value = true
        }
    } finally {
        if (requestSeq === oddsRequestSeq.value) {
            oddsLoading.value = false
        }
    }
}

const refreshOdds = async () => {
    oddsLoaded.value = false
    await fetchOdds(true)
}

const fetchStandings = async () => {
    standingData.value = await getWorldCupStandings() || { stage_name: '', groups: [] }
}

const fetchRanking = async (mode: RankingMode) => {
    if (rankingLoaded.value[mode]) return
    if (mode === 'standings') {
        rankingLoaded.value.standings = true
        return
    }
    const data = await getWorldCupRankings({ type: mode })
    rankingData.value[mode] = data?.list || []
    rankingLoaded.value[mode] = true
}

const fetchNews = async () => {
    if (newsLoaded.value || newsLoading.value) return
    newsLoading.value = true
    try {
        await resolveNewsCategoryId(props.initialCid)

        if (newsCategoryId.value) {
            const res = await getArticleList({
                cid: newsCategoryId.value,
                page_no: 1,
                page_size: 8
            })
            const list = res?.lists || []
            newsList.value = list
        } else {
            newsList.value = []
        }
    } finally {
        newsLoaded.value = true
        newsLoading.value = false
    }
}

const ensureTabData = async (tab: MainTab) => {
    if (tab === 'live') {
        await fetchWorldCupLiveCards()
    } else if (tab === 'schedule') {
        await fetchSchedule()
    } else if (tab === 'odds') {
        await fetchOdds()
    } else if (tab === 'rank') {
        if (rankingMode.value === 'standings') {
            await fetchStandings()
        } else {
            await fetchRanking(rankingMode.value)
        }
    } else if (tab === 'bracket') {
        await fetchSchedule()
    } else if (tab === 'news') {
        await fetchNews()
    }
}

const switchTab = (tab: MainTab) => {
    activeTab.value = tab
}

const switchOddsShowType = (showType: OddsShowType) => {
    if (oddsShowType.value === showType) return
    oddsShowType.value = showType
    void refreshOdds()
}

const confirmOddsSearch = () => {
    const keyword = oddsSearchText.value.trim()
    if (oddsKeyword.value === keyword && oddsLoaded.value) return
    oddsKeyword.value = keyword
    void refreshOdds()
}

const clearOddsKeyword = () => {
    if (!oddsSearchText.value && !oddsKeyword.value) return
    oddsSearchText.value = ''
    oddsKeyword.value = ''
    void refreshOdds()
}

const switchBracketTab = (tab: BracketTabKey) => {
    activeBracketTab.value = tab
}

const toggleScheduleSort = () => {
    scheduleSort.value = scheduleSort.value === 'time' ? 'group' : 'time'
}

const goBack = () => {
    emit('back')
}

const goMatchDetail = (match: any) => {
    const id = match?.id || match?.match_id
    if (!id) return
    uni.navigateTo({ url: `/pages/match_detail/match_detail?id=${id}` })
}

const goOddsMatchDetail = (match: WorldCupOddsMatchItem) => {
    if (!match?.id) return
    goMatchDetail(match)
}

const openWorldCupLiveWebview = (url: string) => {
    uni.navigateTo({ url: `/pages/webview/webview?url=${encodeURIComponent(url)}` })
}

const openWorldCupLiveCard = (live: WorldCupLiveCardItem) => {
    const playUrl = resolveWorldCupLivePlayUrl(live)
    const sourceUrl = resolveWorldCupLiveSourceUrl(live)
    if (!playUrl && !sourceUrl) {
        uni.showToast({ title: '暂无直播链接', icon: 'none' })
        return
    }

    if (useLiveCardPosterMode.value) {
        openWorldCupLiveWebview(sourceUrl || playUrl)
        return
    }

    try {
        const videoContext = uni.createVideoContext(buildWorldCupLiveVideoId(live))
        videoContext?.requestFullScreen?.({
            direction: 90,
        })
        videoContext?.play?.()
    } catch {
        uni.showToast({ title: '当前设备暂不支持全屏', icon: 'none' })
    }
}

const getWorldCupDisplayDate = (timestamp: number) => {
    return getLocalMatchDate(timestamp, WORLD_CUP_MATCH_CONTEXT)
}

const formatDateKeyFromDate = (date: Date | null) => {
    if (!date) return '0'
    const y = date.getFullYear()
    const m = String(date.getMonth() + 1).padStart(2, '0')
    const day = String(date.getDate()).padStart(2, '0')
    return `${y}-${m}-${day}`
}

const formatDateKey = (timestamp: number) => {
    if (!timestamp) return '0'
    return formatDateKeyFromDate(getWorldCupDisplayDate(timestamp))
}

const formatDateLabel = (timestamp: number) => {
    if (!timestamp) return '未分组'
    const d = getWorldCupDisplayDate(timestamp)
    if (!d) return '未分组'
    const weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
    return `${d.getFullYear()}年${d.getMonth() + 1}月${d.getDate()}日 ${weeks[d.getDay()]}`
}

const normalizeGroupName = (value: string) => {
    if (!value) return '未分组'
    if (/^[A-Z]$/.test(value)) return `${value}组`
    return value
}

const formatMatchTime = (timestamp: number) => {
    if (!timestamp) return '--'
    const date = getWorldCupDisplayDate(timestamp)
    if (!date) return '--'
    return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`
}

const formatBracketDate = (timestamp: number) => {
    if (!timestamp) return '--'
    const date = getWorldCupDisplayDate(timestamp)
    if (!date) return '--'
    return `${date.getMonth() + 1}月${date.getDate()}日`
}

const getTodayScheduleDateKey = () => formatDateKeyFromDate(new Date())

const resolveTodayScheduleAnchorId = () => {
    const todayKey = getTodayScheduleDateKey()
    if (!todayKey) return ''

    if (scheduleSort.value === 'time') {
        const group = scheduleGroups.value.find((item) => item.key === todayKey && item.items.length)
        if (group) return scheduleGroupAnchorId(group.key)
    }

    const group = scheduleGroups.value.find((item) =>
        item.items.some((match: any) => formatDateKey(match.match_time) === todayKey)
    )
    if (!group) return ''
    return scheduleGroupAnchorId(group.key)
}

const scrollScheduleToToday = async () => {
    if (activeTab.value !== 'schedule') return

    const targetId = resolveTodayScheduleAnchorId()
    if (!targetId) return

    scheduleScrollIntoView.value = ''
    await nextTick()
    scheduleScrollIntoView.value = targetId
}

const matchCenterText = (match: any) => {
    if (match.status === 1) return match.current_minute || '进行中'
    if (match.status === 2) return `${match.home_score}-${match.away_score}`
    if (match.status === 3) return '已推迟'
    return formatMatchTime(match.match_time)
}

const matchMetaText = (match: any, index: number) => {
    const parts: string[] = []
    if (match.stage) parts.push(normalizeGroupName(match.stage))
    if (match.round_name && match.round_name !== match.stage) parts.push(match.round_name)
    if (match.round_index || index >= 0) parts.push(`第${match.round_index || index + 1}场`)
    return parts.join(' · ') || '世界杯'
}

const oddsMatchKey = (match: WorldCupOddsMatchItem) => {
    const sourceId = match.source_match_ids?.[0] || ''
    return `${match.home_team}-${match.away_team}-${match.match_time_text || match.match_time || sourceId}`
}

const oddsCenterText = (match: WorldCupOddsMatchItem) => {
    if (match.status === 1) return match.current_minute || '进行中'
    if (match.status === 2) return `${match.home_score || 0}-${match.away_score || 0}`
    return 'VS'
}

const oddsTimeText = (match: WorldCupOddsMatchItem) => {
    if (match.match_time) {
        return formatMatchTime(match.match_time)
    }
    return match.match_time_text || '--'
}

const formatOddsUpdateTime = (timestamp?: number) => {
    const value = Number(timestamp || 0)
    if (!value) return ''
    const date = new Date(value * 1000)
    const month = String(date.getMonth() + 1).padStart(2, '0')
    const day = String(date.getDate()).padStart(2, '0')
    const hour = String(date.getHours()).padStart(2, '0')
    const minute = String(date.getMinutes()).padStart(2, '0')
    return `${month}-${day} ${hour}:${minute}`
}

const initViewState = async () => {
    initLayout()

    const legacyTab = String(props.initialTab || 'live')
    await resolveNewsCategoryId(props.initialCid)
    if (legacyTab === 'live') {
        activeTab.value = 'live'
    } else if (legacyTab === 'schedule') {
        activeTab.value = 'schedule'
    } else if (legacyTab === 'odds' && showStandaloneOddsTab) {
        activeTab.value = 'odds'
    } else if (legacyTab === 'odds') {
        activeTab.value = 'schedule'
    } else if (legacyTab === 'rank' || legacyTab === 'standings') {
        activeTab.value = 'rank'
        rankingMode.value = 'standings'
    } else if (legacyTab === 'goals') {
        activeTab.value = 'rank'
        rankingMode.value = 'goals'
    } else if (legacyTab === 'assists') {
        activeTab.value = 'rank'
        rankingMode.value = 'assists'
    } else if (legacyTab === 'news') {
        activeTab.value = 'news'
    } else {
        activeTab.value = 'bracket'
    }

    await Promise.all([fetchSchedule(), fetchStandings()])

    if (activeTab.value === 'rank' && rankingMode.value !== 'standings') {
        await fetchRanking(rankingMode.value)
    }
    if (activeTab.value === 'odds') {
        await fetchOdds()
    }
    if (activeTab.value === 'news') {
        await fetchNews()
    }
}

watch(activeTab, (tab) => {
    ensureTabData(tab)
}, { immediate: true })

watch(rankingMode, () => {
    if (activeTab.value === 'rank') {
        ensureTabData('rank')
    }
})

watch(scheduleSort, () => {
    if (activeTab.value === 'schedule') {
        void scrollScheduleToToday()
    }
})

onMounted(() => {
    initViewState()
})
</script>

<style lang="scss" scoped>
.worldcup-page {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: #fff;
    overflow: hidden;
}

.worldcup-header {
    position: relative;
    background: linear-gradient(180deg, #3552ff 0%, #2c48ea 100%);
    color: #fff;
    overflow: hidden;
    flex-shrink: 0;
    padding-bottom: 2px;
    margin-bottom: 2px;
}

.worldcup-header__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12rpx 14rpx 0;
}

.worldcup-header__back,
.worldcup-header__switch {
    width: 56rpx;
    height: 56rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.worldcup-header__switch {
    width: auto;
    min-width: 82rpx;
    padding: 0 14rpx;
    border-radius: 999rpx;
    background: rgba(255, 255, 255, 0.16);
    font-size: 24rpx;
    font-weight: 600;
    color: #fff;
    line-height: 1;
}

.worldcup-header__hero {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 0 14rpx 14rpx;
}

.worldcup-header__watermark {
    position: absolute;
    top: -6rpx;
    left: 50%;
    transform: translateX(-50%);
    font-size: 170rpx;
    font-weight: 900;
    line-height: 1;
    color: rgba(255, 255, 255, 0.08);
}

.worldcup-header__badge {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 86rpx;
    height: 86rpx;
    border-radius: 22rpx;
    background: rgba(255, 255, 255, 0.15);
    margin-bottom: 8rpx;
    z-index: 1;
}

.worldcup-header__badge-cup {
    font-size: 34rpx;
    line-height: 1;
}

.worldcup-header__badge-label {
    margin-top: 4rpx;
    font-size: 18rpx;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 1rpx;
}

.worldcup-header__title {
    position: relative;
    z-index: 1;
    font-size: 30rpx;
    font-weight: 600;
    line-height: 1.4;
    text-align: center;
}

.worldcup-nav {
    white-space: nowrap;
    padding: 0 14rpx;
    font-size: 0;
    line-height: 0;
}

.worldcup-nav__inner {
    display: inline-flex;
    align-items: center;
    gap: 10rpx;
    white-space: nowrap;
    vertical-align: top;
}

.worldcup-nav__item {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 10rpx 16rpx;
    border-radius: 24rpx;
    font-size: 24rpx;
    line-height: 1;
    color: rgba(255, 255, 255, 0.9);
    flex-shrink: 0;

    &--active {
        background: rgba(255, 255, 255, 0.22);
        color: #fff;
        font-weight: 600;
    }
}

.worldcup-scroll {
    flex: 1;
    height: 0;
    min-height: 0;
    padding: 0 14rpx 0;
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
    box-sizing: border-box;
    background: #fff;
}

.worldcup-section {
    min-height: 100%;
}

.worldcup-sortbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12rpx 34rpx;
    border-radius: 0;
    background: #fff;
    margin: 0 -14rpx 8rpx;
}

.worldcup-sortbar__label {
    font-size: 26rpx;
    color: #111827;
}

.worldcup-sortbar__icon {
    font-size: 30rpx;
    color: #6b7280;
}

.worldcup-group {
    margin-bottom: 14rpx;
}

.worldcup-group__title {
    display: flex;
    align-items: center;
    gap: 6rpx;
    margin: 4rpx 0 10rpx;
    font-size: 26rpx;
    font-weight: 600;
    color: #111827;
}

.worldcup-group__dot {
    width: 12rpx;
    height: 12rpx;
    border-radius: 50%;
    background: #185dff;
    flex-shrink: 0;
}

.worldcup-live-grid {
    display: flex;
    flex-wrap: wrap;
    margin: 12rpx -6rpx 0;
    padding-top: 12rpx;
}

.worldcup-live-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 12rpx;
    width: calc(50% - 12rpx);
    min-width: 0;
    box-sizing: border-box;
    margin: 0 6rpx 12rpx;
    padding: 20rpx 18rpx;
    border-radius: 22rpx;
    background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
    box-shadow: 0 10rpx 28rpx rgba(37, 99, 235, 0.08);
}

.worldcup-live-card__player-wrap {
    position: relative;
    width: 100%;
    height: 210rpx;
    border-radius: 18rpx;
    overflow: hidden;
    background: #0f172a;
}

.worldcup-live-card__player-wrap--poster {
    background: linear-gradient(135deg, #0f172a 0%, #1e40af 100%);
}

.worldcup-live-card__player {
    width: 100%;
    height: 100%;
    display: block;
}

.worldcup-live-card__poster {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
}

.worldcup-live-card__poster-image {
    width: 100%;
    height: 100%;
    display: block;
}

.worldcup-live-card__poster-empty {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 18rpx;
    box-sizing: border-box;
    text-align: center;
    color: rgba(255, 255, 255, 0.86);
    font-size: 22rpx;
    font-weight: 600;
    line-height: 1.35;
}

.worldcup-live-card__poster-shade {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    background: rgba(15, 23, 42, 0.28);
}

.worldcup-live-card__play {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 58rpx;
    height: 58rpx;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.24);
    border: 2rpx solid rgba(255, 255, 255, 0.78);
}

.worldcup-live-card__play-icon {
    width: 0;
    height: 0;
    margin-left: 4rpx;
    border-top: 12rpx solid transparent;
    border-bottom: 12rpx solid transparent;
    border-left: 18rpx solid #ffffff;
}

.worldcup-live-card__status {
    position: absolute;
    right: 12rpx;
    top: 12rpx;
    max-width: 128rpx;
    height: 34rpx;
    line-height: 34rpx;
    padding: 0 12rpx;
    border-radius: 999rpx;
    background: rgba(15, 23, 42, 0.58);
    color: #ffffff;
    font-size: 20rpx;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.worldcup-live-card__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10rpx;
}

.worldcup-live-card__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 68rpx;
    height: 36rpx;
    padding: 0 12rpx;
    border-radius: 999rpx;
    background: rgba(53, 82, 255, 0.12);
    color: #3552ff;
    font-size: 22rpx;
    font-weight: 700;
}

.worldcup-live-card__count {
    font-size: 22rpx;
    color: #64748b;
}

.worldcup-live-card__meta {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8rpx;
    min-width: 0;
    font-size: 22rpx;
    color: #64748b;
}

.worldcup-live-card__anchor,
.worldcup-live-card__stats {
    display: flex;
    align-items: center;
    min-width: 0;
}

.worldcup-live-card__anchor {
    gap: 8rpx;
}

.worldcup-live-card__avatar {
    width: 34rpx;
    height: 34rpx;
    border-radius: 50%;
    flex-shrink: 0;
    background: #e2e8f0;
}

.worldcup-live-card__avatar--empty {
    display: flex;
    align-items: center;
    justify-content: center;
    color: #64748b;
    font-size: 18rpx;
}

.worldcup-live-card__anchor-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: #334155;
    font-weight: 600;
}

.worldcup-live-card__stats {
    flex-wrap: wrap;
    gap: 8rpx 12rpx;
}

.worldcup-live-card__stat {
    white-space: nowrap;
}

.worldcup-live-card__notice {
    display: block;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.worldcup-live-card__teams {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    min-width: 0;
}

.worldcup-live-card__line {
    flex: 1;
    min-width: 0;
    font-size: 24rpx;
    font-weight: 600;
    color: #1e293b;
    line-height: 1.4;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wc-match-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16rpx 12rpx;
    margin-bottom: 8rpx;
    border-radius: 18rpx;
    background: #fff;
}

.wc-match-card__team {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 8rpx;

    &--right {
        justify-content: flex-end;
    }
}

.wc-match-card__logo {
    width: 46rpx;
    height: 46rpx;
    flex-shrink: 0;
}

.wc-match-card__team-name {
    font-size: 30rpx;
    font-weight: 600;
    color: #111827;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.wc-match-card__center {
    width: 150rpx;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4rpx;
}

.wc-match-card__time {
    font-size: 32rpx;
    font-weight: 700;
    color: #111827;
    line-height: 1.2;
}

.wc-match-card__meta {
    font-size: 20rpx;
    color: #8b93a7;
    line-height: 1.3;
    text-align: center;
}

.worldcup-odds-filter {
    padding: 10rpx 0 8rpx;
}

.worldcup-odds-filter__tabs {
    white-space: nowrap;
    font-size: 0;
    line-height: 0;
}

.worldcup-odds-filter__tabs-inner {
    display: inline-flex;
    align-items: center;
    gap: 10rpx;
    padding-right: 6rpx;
    vertical-align: top;
}

.worldcup-odds-filter__tab {
    height: 56rpx;
    padding: 0 22rpx;
    border-radius: 14rpx;
    background: #f1f5f9;
    color: #475569;
    font-size: 24rpx;
    font-weight: 700;
    line-height: 56rpx;
    white-space: nowrap;
}

.worldcup-odds-filter__tab--active {
    background: #1d4ed8;
    color: #ffffff;
}

.worldcup-odds-filter__search {
    height: 72rpx;
    margin-top: 14rpx;
    padding: 0 10rpx 0 18rpx;
    border: 1rpx solid #e2e8f0;
    border-radius: 16rpx;
    background: #ffffff;
    display: flex;
    align-items: center;
    gap: 10rpx;
    box-shadow: 0 8rpx 22rpx rgba(15, 23, 42, 0.04);
}

.worldcup-odds-filter__input {
    flex: 1;
    min-width: 0;
    height: 70rpx;
    color: #111827;
    font-size: 26rpx;
    line-height: 70rpx;
}

.worldcup-odds-filter__placeholder {
    color: #94a3b8;
    font-size: 26rpx;
}

.worldcup-odds-filter__clear {
    width: 44rpx;
    height: 44rpx;
    border-radius: 14rpx;
    background: #f1f5f9;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.worldcup-odds-filter__button {
    width: 92rpx;
    height: 52rpx;
    border-radius: 14rpx;
    background: #0f172a;
    color: #ffffff;
    font-size: 24rpx;
    font-weight: 700;
    line-height: 52rpx;
    text-align: center;
    flex-shrink: 0;
}

.worldcup-odds-filter__meta {
    margin-top: 10rpx;
    color: #64748b;
    font-size: 22rpx;
    line-height: 1.4;
}

.worldcup-odds-card {
    margin: 12rpx 0;
    padding: 18rpx 16rpx;
    border-radius: 18rpx;
    background: #fff;
    box-shadow: 0 8rpx 24rpx rgba(15, 23, 42, 0.06);
}

.worldcup-odds-card__head,
.worldcup-odds-platform__head,
.worldcup-odds-platform__name,
.worldcup-odds-card__teams,
.worldcup-odds-card__team {
    display: flex;
    align-items: center;
    min-width: 0;
}

.worldcup-odds-card__head,
.worldcup-odds-platform__head {
    justify-content: space-between;
    gap: 12rpx;
}

.worldcup-odds-card__league {
    flex: 1;
    min-width: 0;
    color: #64748b;
    font-size: 22rpx;
    line-height: 1.35;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.worldcup-odds-card__time,
.worldcup-odds-platform__update {
    flex-shrink: 0;
    color: #94a3b8;
    font-size: 20rpx;
    line-height: 1.3;
}

.worldcup-odds-card__teams {
    justify-content: space-between;
    gap: 12rpx;
    padding: 16rpx 0 12rpx;
}

.worldcup-odds-card__team {
    flex: 1;
    gap: 8rpx;

    &--right {
        justify-content: flex-end;
    }
}

.worldcup-odds-card__logo {
    width: 42rpx;
    height: 42rpx;
    flex-shrink: 0;
}

.worldcup-odds-card__team-name {
    min-width: 0;
    color: #111827;
    font-size: 28rpx;
    font-weight: 700;
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.worldcup-odds-card__vs {
    width: 104rpx;
    flex-shrink: 0;
    text-align: center;
    color: #2563eb;
    font-size: 28rpx;
    font-weight: 800;
    line-height: 1.2;
}

.worldcup-odds-platform {
    padding: 14rpx 0 0;
    border-top: 1rpx solid #eef2f7;

    & + & {
        margin-top: 14rpx;
    }
}

.worldcup-odds-platform__name {
    gap: 8rpx;
    color: #0f172a;
    font-size: 24rpx;
    font-weight: 700;
}

.worldcup-odds-platform__tag {
    height: 32rpx;
    line-height: 32rpx;
    padding: 0 10rpx;
    border-radius: 999rpx;
    background: #eaf1ff;
    color: #2563eb;
    font-size: 20rpx;
    font-weight: 600;
}

.worldcup-odds-market {
    display: grid;
    grid-template-columns: 104rpx minmax(0, 1fr);
    align-items: stretch;
    gap: 10rpx;
    margin-top: 10rpx;
}

.worldcup-odds-market__title {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 4rpx;
    min-width: 0;
    color: #475569;
    font-size: 22rpx;
    line-height: 1.25;
}

.worldcup-odds-market__line {
    color: #0f172a;
    font-size: 24rpx;
    font-weight: 700;
}

.worldcup-odds-market__values {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8rpx;
    min-width: 0;
}

.worldcup-odds-value {
    min-width: 0;
    padding: 10rpx 8rpx;
    border-radius: 12rpx;
    background: #f8fafc;
    text-align: center;
}

.worldcup-odds-value__label,
.worldcup-odds-value__number {
    display: block;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.worldcup-odds-value__label {
    color: #64748b;
    font-size: 20rpx;
    line-height: 1.2;
}

.worldcup-odds-value__number {
    margin-top: 4rpx;
    color: #dc2626;
    font-size: 26rpx;
    font-weight: 800;
    line-height: 1.2;
}

.bracket-round-nav {
    margin-bottom: 10rpx;
    white-space: nowrap;
    font-size: 0;
    line-height: 0;
}

.bracket-round-nav__inner {
    display: inline-flex;
    align-items: center;
    gap: 10rpx;
    padding-right: 6rpx;
    vertical-align: top;
}

.bracket-round-nav__item {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 8rpx 18rpx;
    border-radius: 24rpx;
    background: #fff;
    color: #7b8190;
    font-size: 24rpx;
    line-height: 1;
    flex-shrink: 0;

    &--active {
        background: #2f67ff;
        color: #fff;
        font-weight: 600;
    }
}

.bracket-stage {
    overflow: hidden;
}

.bracket-stage__list {
    display: flex;
    flex-direction: column;
    gap: 10rpx;
}

.bracket-stage__list--final {
    gap: 8rpx;
}

.bracket-stage__pair {
    display: grid;
    grid-template-columns: minmax(0, 8fr) minmax(64rpx, 2fr);
    align-items: stretch;
    column-gap: 0;
}

.bracket-stage__cards {
    display: flex;
    flex-direction: column;
    gap: 6rpx;
    min-width: 0;
}

.bracket-stage__linezone {
    position: relative;
    min-width: 64rpx;

    &::before,
    &::after {
        content: '';
        position: absolute;
        border-color: #2f67ff;
        border-style: solid;
    }

    &::before {
        left: 0;
        top: 70rpx;
        width: 24rpx;
        height: 150rpx;
        border-top-width: 2rpx;
        border-right-width: 2rpx;
        border-bottom-width: 2rpx;
        border-left-width: 0;
        border-radius: 0 18rpx 18rpx 0;
    }

    &::after {
        left: 24rpx;
        top: 145rpx;
        width: calc(100% - 24rpx);
        height: 1px;
        background: #2f67ff;
        border: 0;
        transform: translateY(-50%);
    }
}

.bracket-stage__item {
    position: relative;
}

.bracket-stage__card {
    display: flex;
    align-items: center;
    min-height: 140rpx;
    padding: 14rpx 14rpx;
    border-radius: 24rpx;
    background: #fff;
    box-sizing: border-box;
}

.bracket-stage__time {
    width: 86rpx;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 8rpx;
    flex-shrink: 0;
}

.bracket-stage__clock {
    font-size: 30rpx;
    font-weight: 600;
    line-height: 1;
    color: #111827;
}

.bracket-stage__date {
    font-size: 18rpx;
    line-height: 1;
    color: #8b93a7;
}

.bracket-stage__divider {
    width: 1rpx;
    align-self: stretch;
    margin: 0 12rpx 0 10rpx;
    background: #edf0f5;
    flex-shrink: 0;
}

.bracket-stage__teams {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 8rpx;
}

.bracket-stage__team {
    display: flex;
    align-items: center;
    gap: 10rpx;
}

.bracket-stage__logo {
    width: 42rpx;
    height: 22rpx;
    flex-shrink: 0;
    background: #f2f4f7;
    border-radius: 2rpx;
}

.bracket-stage__name {
    flex: 1;
    min-width: 0;
    font-size: 28rpx;
    line-height: 1.3;
    color: #111827;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bracket-stage__name--multi {
    white-space: normal;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}

.bracket-extra {
    margin-top: 10rpx;
}

.bracket-extra__title {
    display: block;
    margin-bottom: 8rpx;
    font-size: 24rpx;
    font-weight: 500;
    color: #111827;
}

.worldcup-empty,
.worldcup-loading {
    padding: 80rpx 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.worldcup-loading {
    flex-direction: column;
    gap: 12rpx;
    color: #8b93a7;
    font-size: 24rpx;
}
</style>
