<template>
  <div class="pc-sports-list-container" >
    <el-scrollbar height="100%" @end-reached="onLoadMore">
      <div class="league-list-wrapper">
        <div class="league-group" v-for="(league, lIndex) in leagueList" :key="league.id">
          
          <div class="league-header" @click="toggleLeague(lIndex)">
            <div class="l-left">
              <el-avatar :src="league.logo" :size="24" style="background-color: transparent;"></el-avatar>
              <span class="l-name">{{ locale === 'zh' ? league.league : league.league_en }}</span>
            </div>
            <div class="l-right">
              <span class="l-count">{{ league.sport_count }}</span>
              <el-icon class="l-icon">
                <ArrowUp v-if="league.isExpanded" />
                <ArrowDown v-else />
              </el-icon>
            </div>
          </div>

          <el-collapse-transition>
            <div class="league-matches" v-show="league.isExpanded">
              <div class="loading-wrap" v-if="league.loadingMatches" v-loading="true" style="height: 60px;"></div>
              
              <div class="matches-wrap" v-else>
                <div
                  class="match-card"
                  v-for="item in league.matches"
                  :key="item.data_id || item.id"
                >
                  <div class="match-card-header">
                    <div class="match-status-info">
                      <div class="decorate-bar"></div>
                      <span class="status-text" :class="{'text-live': item.state === 1}">
                        {{ getStatusText(item.state) }}
                      </span>
                      <el-tag style="margin-left: 10px" size="small" v-if="item.state === 1 && item.fixture_status">
                        {{ item.fixture_status?.long }}
                      </el-tag>
                      <el-tag v-if="item.is_roll === 1" style="margin-left: 10px" type="warning">{{ t('滚球') }}</el-tag>
                      <span v-if="item.state === 1" class="live-timer-span">
                        <span class="live-dot"></span>
                        <template v-if="item.fixture_status">{{ item.fixture_status?.seconds }}</template>
                      </span>
                    </div>
                    <div class="match-status-time">
                      <span style="font-size: 13px;color: #999">{{ item.game_time || '--:--' }}</span>
                    </div>
                  </div>

                  <div class="match-card-main" @click="goDetail(item)">
                    <div class="match-teams">
                      <div class="team-row">
                        <div style="display: flex;align-items: center;gap: 6px;">
                          <div class="team-info">
                            <el-avatar :src="item.home_team_logo" :size="24" class="team-logo"></el-avatar>
                            <span class="team-name" :title="locale === 'zh' ? item.home_team : item.home_team_en">
                              {{ locale === 'zh' ? item.home_team : item.home_team_en }}
                            </span>
                          </div>
                          <el-tag size="small" type="success">{{ t('主') }}</el-tag>
                        </div>
                        <span class="team-score" v-if="item.state !== 0" :class="{'text-live': item.state === 1}">
                          {{ getScore(item.score, 0) }}
                        </span>
                      </div>

                      <div class="team-row mt-3">
                        <div style="display: flex;align-items: center;gap: 6px;">
                          <div class="team-info">
                            <el-avatar :src="item.guest_team_logo" :size="24" class="team-logo"></el-avatar>
                            <span class="team-name" :title="locale === 'zh' ? item.guest_team : item.guest_team_en">
                              {{ locale === 'zh' ? item.guest_team : item.guest_team_en }}
                            </span>
                          </div>
                          <el-tag size="small" type="danger">{{ t('客') }}</el-tag>
                        </div>
                        <span class="team-score" v-if="item.state !== 0" :class="{'text-live': item.state === 1}">
                          {{ getScore(item.score, 1) }}
                        </span>
                      </div>
                    </div>

                    <div class="match-odds-grids">
                      <template v-if="[0, 1].includes(item.state) && item.odds && item.odds.length > 0">
                        <div class="market-col" v-for="(market, m) in item.odds.slice(0, 3)" :key="market.id">
                          <div class="market-name" :title="locale === 'zh' ? market.name : market.name_en">{{ locale === 'zh' ? market.name : market.name_en }}</div>
                          
                          <div class="preview-pair-headers" v-if="hasPairHeaders(market)">
                            <div class="preview-pair-item">{{ getPairHeaders(market)[0] }}</div>
                            <div class="preview-pair-item">{{ getPairHeaders(market)[1] }}</div>
                          </div>
                          <div class="preview-pair-headers" v-else></div> <div :class="['market-values', m > 0 ? 'market-values-border-left' : '']">
                            <div
                                class="odds-btn"
                                v-for="(opt, optIndex) in getPreviewMarketValues(market)"
                                :key="optIndex"
                                :class="{
                                  'is-locked': item.is_locked || opt.suspended || !opt.odd || market.is_findLocked,
                                  'is-active': isSelected(item.id, market.id, opt),
                                  'is-centered-odds': (hasPairHeaders(market) && pairPriority[opt.value]) && !opt.handicap_text
                                }"
                                @click.stop="handleOddsClick(item, market, opt)"
                            >
                              <div class="odds-name-wrapper" v-if="!(hasPairHeaders(market) && pairPriority[opt.value]) || opt.handicap_text">
                                <span class="selection-name" style="margin-right: 4px" v-if="!(hasPairHeaders(market) && pairPriority[opt.value])" :title="locale === 'zh' ? opt.value_text : opt.value">
                                  {{ translateSelection(locale === 'zh' ? opt.value_text : opt.value) }}
                                </span>
                                <span class="handicap-val" v-if="opt.handicap_text">{{ opt.handicap_text }}</span>
                              </div>
                              <div class="odds-val-wrapper">
                                <el-icon v-if="!opt.odd || opt.suspended || item.is_locked || market.is_findLocked" class="lock-icon"><Lock /></el-icon>
                                <span v-else class="odds-val"><span>{{ opt.odd || opt.odd === 0 ? opt.odd : '-' }}</span></span>
                              </div>
                            </div>
                          </div>
                        </div>
                      </template>
                      <div class="empty-odds-tip" v-else>
                        <span class="empty-text" v-if="item.state !== 2">{{ t('暂无盘口数据') }}</span>
                        <span class="empty-text" v-else>{{ t('已完场') }}</span>
                      </div>
                    </div>

                    <div class="match-more-toggle" @click.stop="goDetail(item)">
                      <div class="more-content" v-if="item.odds_count > 0">
                        <span class="more-text">+{{ item.odds_count }}</span>
                      </div>
                      <span v-else class="empty-more">--</span>
                    </div>
                  </div>
                </div>

                <el-empty v-if="!league.matches || league.matches.length === 0" :description="t('暂无赛事数据')" :image-size="60"></el-empty>
              </div>
            </div>
          </el-collapse-transition>
        </div>

        <div class="loading-more" v-if="leagueList.length > 0">
          <span>{{ isNoMore ? t('没有更多了') : t('上拉加载更多') }}</span>
        </div>
        <el-empty v-if="leagueList.length === 0 && !isFetching" :description="t('暂无数据')"></el-empty>
      </div>
    </el-scrollbar>
  </div>
</template>

<script setup>
import { ref, watch, onMounted } from 'vue';
import { useI18n } from "vue-i18n";
import { useRouter } from 'vue-router';
import { getLeagueList, getSportSchedule } from "@/request/api.js"; 
import { useOrderStore } from "@/store/bettingSheet.js";
import { ArrowDown, ArrowUp, Lock } from '@element-plus/icons-vue';
import { threeColMarkets, pairPriority } from '../config.js';

const { t, locale } = useI18n();
const router = useRouter();
const orderStore = useOrderStore();

const props = defineProps({
  keyword: { type: String, default: '' }
});

const leagueList = ref([]);
const page = ref(1);
const limit = ref(20);
const isFetching = ref(false);
const isNoMore = ref(false);
const selectedMap = ref({});

const translateSelection = (valStr) => valStr === undefined || valStr === null ? '' : String(valStr);

// 解析比赛状态文本
const getStatusText = (state) => {
  const states = { 0: t("未开始"), 1: t("进行中"), 2: t("已完场"), 3: t("延期"), 4: t("取消") };
  return states[state] || t("未知");
};

// 提取双列头部名称
const getPairHeaders = (market) => {
  if (!market || !market.values) return ['', ''];
  let left = '';
  let right = '';
  for (const v of market.values) {
    if (pairPriority[v.value] === 1 && !left) {
      left = translateSelection(locale.value === 'zh' ? v.value_text : v.value);
    } else if (pairPriority[v.value] === 2 && !right) {
      right = translateSelection(locale.value === 'zh' ? v.value_text : v.value);
    }
  }
  return [left, right];
};

// 判断是否需要显示双列头部
const hasPairHeaders = (market) => {
  if (threeColMarkets.includes(market.name_en)) return false;
  const headers = getPairHeaders(market);
  return !!(headers[0] || headers[1]);
};

const zipperSort = (market, values) => {
  if (!values) return [];
  if (threeColMarkets.includes(market.name_en)) return values;
  
  const lefts = [], rights = [], others = [];
  values.forEach(v => {
    const p = pairPriority[v.value];
    if (p === 1) lefts.push(v);
    else if (p === 2) rights.push(v);
    else others.push(v);
  });

  let sortedValues = [];
  if (lefts.length > 0 || rights.length > 0) {
    const maxLen = Math.max(lefts.length, rights.length);
    for (let i = 0; i < maxLen; i++) {
      if (lefts[i]) sortedValues.push(lefts[i]);
      if (rights[i]) sortedValues.push(rights[i]);
    }
    sortedValues = sortedValues.concat(others);
  } else {
    sortedValues = [...values];
  }
  return sortedValues;
};

const getPreviewMarketValues = (market) => {
  const sorted = zipperSort(market, market.values);
  if (threeColMarkets.includes(market.name_en)) return sorted.slice(0, 3);
  return sorted.slice(0, 2);
};

onMounted(() => {
  fetchLeagueList(1);
  syncFromStore();
});

const fetchLeagueList = async (pageNum) => {
  if (isFetching.value || (isNoMore.value && pageNum !== 1)) return;
  isFetching.value = true;
  if (pageNum === 1) {
    leagueList.value = [];
    isNoMore.value = false;
  }

  try {
    const params = { page: pageNum, limit: limit.value };
    if (props.keyword) params.keyword = props.keyword;
    
    const res = await getLeagueList(params);
    if (res.code === 1 && res.data && res.data.list) {
      const formattedList = res.data.list.map(league => ({
        ...league,
        isExpanded: false,
        loadingMatches: false,
        matches: []
      }));
      
      leagueList.value = pageNum === 1 ? formattedList : [...leagueList.value, ...formattedList];
      if (res.data.list.length < limit.value) isNoMore.value = true;
      page.value = pageNum;
    } else {
      isNoMore.value = true;
    }
  } catch (error) {
    console.error("Fetch league list failed", error);
  } finally {
    isFetching.value = false;
  }
};

const onLoadMore = () => {
  if (!isNoMore.value) fetchLeagueList(page.value + 1);
};

const refresh = () => {
  fetchLeagueList(1);
};
defineExpose({ refresh });

const toggleLeague = async (index) => {
  const target = leagueList.value[index];
  target.isExpanded = !target.isExpanded;
  
  if (target.isExpanded && (!target.matches || target.matches.length === 0)) {
    target.loadingMatches = true;
    try {
      const res = await getSportSchedule({ page: 1, limit: 50, league_id: target.league_id, from: 'pc' });
      if (res.code === 1 && res.data && res.data.list) {
        target.matches = res.data.list.map(item => {
          if (typeof item.odds === 'string') {
            try { item.odds = JSON.parse(item.odds); } catch(e) { item.odds = []; }
          }
          if (item.odds && Array.isArray(item.odds)) {
            item.odds.forEach(jtem => {
              if (item.odd_ids_locked && Array.isArray(item.odd_ids_locked) && item.odd_ids_locked.find(trim => jtem.id === trim)) {
                jtem.is_findLocked = true;
              }
            });
          }
          return item;
        });
      }
    } catch (e) {
      console.error(e);
    } finally {
      target.loadingMatches = false;
    }
  }
};

const goDetail = (item) => {
  router.push({ name: 'SportDetail', query: { data_id: item.data_id } });
};

const getScore = (scoreStr, index) => {
  if (!scoreStr || scoreStr === '-') return '0';
  const parts = scoreStr.split('-');
  return parts[index] || '0';
};

const getUniqueKey = (matchId, marketId, selection) => {
  if (selection.handicap !== null && selection.handicap !== undefined && selection.handicap !== '') {
    return `${matchId}_${marketId}_${selection.value}_${selection.handicap}`;
  }
  return `${matchId}_${marketId}_${selection.value}`;
};

const isSelected = (matchId, marketId, selection) => {
  if (!selection) return false;
  const uniqueKey = getUniqueKey(matchId, marketId, selection);
  return !!selectedMap.value[uniqueKey];
};

const handleOddsClick = (item, market, selection) => {
  if (item.state !== 0 && item.state !== 1) return;
  if (item.is_locked || market.is_findLocked) return;
  if (!selection || !selection.odd || selection.odd === '-') return;
  if (selection.suspended) return;

  const uniqueKey = getUniqueKey(item.id, market.id, selection);

  if (selectedMap.value[uniqueKey]) {
    orderStore.removeOrderItemByKey(uniqueKey);
  } else {
    const betItem = {
      matchId: item.id, data_id: item.data_id, league: item.league, league_en: item.league_en,
      homeTeam: item.home_team, home_team_en: item.home_team_en, guestTeam: item.guest_team, guest_team_en: item.guest_team_en,
      betType: market.name, betTypeEn: market.name_en, betTypeName: selection.value_text, betTypeNameEn: selection.value,
      handicap: selection.handicap, handicap_text: selection.handicap_text, odds: selection.odd, score: item.score,
      state: item.state, uniqueKey: uniqueKey, optionValue: selection.value, marketId: market.id,
             mininum: market.mininum, // 新增：最低限额
      maxinum: market.maxinum, // 新增：最高限额
      selection: {
        ...selection
      }
    };
    orderStore.addOrderItem(betItem);

    if (market.values) {
      market.values.forEach(wsItem => {
        const otherKey = getUniqueKey(item.id, market.id, wsItem);
        if (selectedMap.value[otherKey] && otherKey !== uniqueKey) {
          orderStore.removeOrderItemByKey(otherKey);
        }
      });
    }
  }
};

const syncFromStore = () => {
  const map = {};
  if (orderStore.selectOrders && orderStore.selectOrders.length) {
    orderStore.selectOrders.forEach(order => {
      if (order.uniqueKey) map[order.uniqueKey] = true;
    });
  }
  selectedMap.value = map;
};

watch(() => orderStore.selectOrders, () => {
  syncFromStore();
}, { deep: true });
</script>

<style scoped lang="scss">
$main-color: #f8b932;
$card-bg: var(--el-bg-color-overlay);
$border-color: var(--el-border-color-lighter);
$hover-bg: var(--el-fill-color-light);

.pc-sports-list-container {
  height: 100%;
  box-sizing: border-box;
  container-type: inline-size;
  container-name: sports-list;
}
.league-list-wrapper {
  padding-bottom: 20px;
}
.league-group {
  background-color: $card-bg;
  border-radius: 8px;
  margin-bottom: 10px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.05);
  border: 1px solid $border-color;
  overflow: hidden;
}
.league-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  cursor: pointer;
  background-color: var(--el-fill-color-lighter);
  transition: background-color 0.2s;
  &:hover { background-color: var(--el-fill-color-light); }
  .l-left {
    display: flex; align-items: center; gap: 10px;
    .l-name { font-size: 14px; font-weight: bold; color: var(--el-text-color-primary); }
  }
  .l-right {
    display: flex; align-items: center; gap: 8px;
    .l-count { font-size: 13px; color: var(--el-text-color-regular); background: var(--el-fill-color); padding: 2px 8px; border-radius: 10px;}
    .l-icon { color: var(--el-text-color-secondary); }
  }
}
.league-matches {
  border-top: 1px solid $border-color;
  padding: 10px;
}

.match-card {
  background-color: $card-bg; border-radius: 6px; border: 1px solid $border-color; overflow: hidden; margin-bottom: 8px;
  &:hover { border-color: var(--el-border-color); .team-info { text-decoration: underline; } }

  .match-card-header {
    display: flex; justify-content: space-between; align-items: center; padding: 6px 12px; background-color: var(--el-fill-color-lighter); border-bottom: 1px solid $border-color;
    @container sports-list (max-width: 550px) { padding: 6px 10px; flex-wrap: wrap; gap: 4px; }
    .match-status-info {
      display: flex; align-items: center;
      .decorate-bar { width: 3px; height: 12px; background-color: $main-color; border-radius: 2px; margin-right: 6px; }
      .status-text { font-size: 12px; font-weight: bold; color: var(--el-text-color-regular); }
      .text-live { color: var(--el-color-danger); }
      .live-timer-span { font-size: 12px; color: var(--el-color-danger); margin-left: 10px; display: flex; align-items: center; gap: 4px; font-weight: bold; }
      .live-dot { width: 6px; height: 6px; background-color: var(--el-color-danger); border-radius: 50%; animation: pulse 1.5s infinite; }
    }
  }

  .match-card-main {
    display: flex; align-items: stretch; cursor: pointer; transition: background-color 0.2s;
    &:hover { background-color: $hover-bg; }
    @container sports-list (max-width: 550px) { flex-direction: column; }

    .match-teams {
      width: 180px; flex-shrink: 0; padding: 8px 12px; border-right: 1px dashed $border-color; display: flex; flex-direction: column; justify-content: center;
      @container sports-list (max-width: 550px) { width: 100%; border-right: none; border-bottom: 1px dashed $border-color; padding: 8px; flex-direction: row; align-items: center; gap: 16px; }
      .team-row {
        display: flex; justify-content: space-between; align-items: center;
        @container sports-list (max-width: 550px) { flex: 1; }
        &.mt-3 { margin-top: 6px; @container sports-list (max-width: 550px) { margin-top: 0; } }
        .team-info {
          display: flex; align-items: center; gap: 6px; flex: 1; overflow: hidden;
          .team-name { font-size: 12px; font-weight: 500; color: var(--el-text-color-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @container sports-list (max-width: 800px) { font-size: 11px; } }
        }
        .team-score { font-size: 14px; font-weight: 800; color: var(--el-text-color-primary); padding-left: 6px; &.text-live { color: $main-color; } }
      }
    }

    .match-odds-grids {
      flex: 1; padding: 8px 12px; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px;
      @container sports-list (max-width: 1200px) { gap: 20px; }
      @container sports-list (max-width: 800px) { padding: 6px 8px; gap: 20px; }
      @container sports-list (max-width: 1350px) { grid-template-columns: repeat(2, minmax(0, 1fr)); .market-col:nth-child(n+3) { display: none; } }
      @container sports-list (max-width: 992px) { grid-template-columns: repeat(1, minmax(0, 1fr)); .market-col:nth-child(n+2) { display: none; } }

      .market-col {
        display: flex; flex-direction: column;
        .market-name { font-size: 11px; color: var(--el-text-color-secondary); margin-bottom: 4px; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        
        .preview-pair-headers {
          display: flex; gap: 4px; width: 100%; margin-bottom: 10px;
          min-height: 16px; /* 增加最小高度撑开占位 */
          .preview-pair-item {
            flex: 1; text-align: center; font-size: 11px; color: var(--el-text-color-secondary); line-height: 16px;
          }
        }

        .market-values { display: flex; gap: 4px; width: 100%;       position: relative;}
          .market-values-border-left::before{
          content: '';
          position: absolute;
          left: -10px;
          width: 1px;
          height: 80%;
          top: 10%;
          background-color: $main-color;
          opacity: 0.5;
        }
      }
      .empty-odds-tip { grid-column: 1 / -1; display: flex; align-items: center; justify-content: flex-start; padding-left: 10px; .empty-text { color: var(--el-text-color-placeholder); font-size: 12px; } }
    }

    .match-more-toggle {
      width: 100px; flex-shrink: 0; border-left: 1px dashed $border-color; display: flex; flex-direction: column; align-items: center; justify-content: center; transition: background-color 0.2s;
      @container sports-list (max-width: 800px) { width: 44px; }
      @container sports-list (max-width: 550px) { width: 100%; height: 28px; border-left: none; border-top: 1px dashed $border-color; flex-direction: row; }
      &:hover { background-color: var(--el-border-color-extra-light); }
      .more-content { display: flex; flex-direction: column; align-items: center; gap: 2px; color: var(--el-color-primary); font-size: 11px; font-weight: bold; @container sports-list (max-width: 550px) { flex-direction: row; } }
      .empty-more { color: var(--el-text-color-placeholder); font-size: 11px;}
    }
  }
}

.odds-btn {
  flex: 1; min-width: 0; background-color: var(--el-fill-color); border: 1px solid var(--el-border-color); border-radius: 4px;
  display: flex; flex-direction: row; justify-content: space-between; align-items: center; padding: 6px 8px; box-sizing: border-box;
  transition: all 0.2s; cursor: pointer; position: relative; overflow: hidden; min-height: 40px;

  &.is-centered-odds {
    justify-content: center;
  }

  .odds-name-wrapper {
    display: flex; flex-direction: row; align-items: center; justify-content: flex-start; min-width: 0; flex: 1; margin-right: 6px; z-index: 1;
    .selection-name { font-size: 12px; color: var(--el-text-color-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: left; }
    .handicap-val { font-size: 12px; color: var(--el-text-color-primary); font-weight: bold; margin-left: 4px; flex-shrink: 0; }
  }
  .odds-val-wrapper {
    display: flex; align-items: center; justify-content: flex-end; flex-shrink: 0; z-index: 1; gap: 4px;
    .odds-val { display: flex; align-items: center; font-size: 13px; font-weight: bold; color: $main-color; }
  }

  &:hover { border-color: $main-color; background-color: var(--el-fill-color-light); }
  &.is-active { background-color: $main-color; border-color: $main-color; .odds-name-wrapper .selection-name, .odds-name-wrapper .handicap-val, .odds-val-wrapper .odds-val { color: #fff; font-weight: bold } }
  &.is-locked { cursor: not-allowed; border-color: transparent; .selection-name, .handicap-val, .odds-val { opacity: 0.3; } &::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.4); z-index: 2; } .lock-icon { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #fff; font-size: 14px; z-index: 3; } }
}

.market-values { container-type: inline-size; container-name: odds-wrapper; display: flex; gap: 4px; width: 100%; }

/* 已移除导致小屏幕纵向排列的 container 查询，确保所有尺寸下均为横排 */

.loading-more { text-align: center; padding: 15px 0; font-size: 13px; color: var(--el-text-color-secondary); }

@keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.4; } 100% { opacity: 1; } }
</style>