<template>
  <div class="tournament-bracket-root">
    <h1>单败淘汰赛赛程树状图</h1>
    <div class="container">
      <div class="control-panel">
        <h2>选择比赛</h2>
        <div class="tournament-info">
          <select v-model="selectedTournamentId" @change="handleTournamentChange">
            <option value="">-- 请选择比赛 --</option>
            <option v-for="tournament in tournaments" :key="tournament.id" :value="tournament.id">
              {{ tournament.name }}
            </option>
          </select>
          <div v-if="selectedTournamentId">
            <strong>已选择:</strong> {{ selectedTournamentName }}
          </div>
        </div>

        <h2>参赛者列表</h2>
        <div id="player-list">
          <div v-if="!selectedTournamentId" class="loading">请先选择比赛</div>
          <div v-else-if="loading" class="loading">加载中...</div>
          <div v-else>
            <p v-if="participants.length === 0">暂无参赛者</p>
<template v-else>
              <p>共 {{ participants.length }} 位参赛者</p>
              <ul>
                <li v-for="participant in participants" :key="participant.id">
                  {{ participant.name }}
                </li>
              </ul>
            </template>
          </div>
        </div>

        <h2>生成赛程</h2>
        <button @click="generateBracket" :disabled="!canGenerateBracket">生成单败淘汰赛程</button>

        <div v-if="finalRanking" id="finalRanking">
          <h3>最终排名</h3>
          <p>冠军: {{ finalRanking.champion }}</p>
          <p>亚军: {{ finalRanking.runnerUp }}</p>
          <p>季军: {{ finalRanking.thirdPlace }}</p>
        </div>
      </div>

      <div class="bracket-container" id="bracketContainer">
        <div class="bracket" id="bracket">
          <template v-for="(roundMatches, rIdx) in roundsMatches" :key="rIdx">
            <div class="round">
              <div class="round-title">第 {{ rIdx + 1 }} 轮</div>
              <template v-for="match in roundMatches" :key="match.id">
                <div class="match" :id="'match-' + match.id">
                  <!-- 参赛者1 -->
                  <div class="participant" :class="{ winner: match.winner && match.participant1 && match.winner.id === match.participant1.id }">
                    {{ match.participant1 ? match.participant1.name : '轮空' }}
                    <input type="number" min="0" class="score-input"
                      v-model.number="match.score1"
                      :disabled="match.decided || !match.participant1 || !match.participant2"
                      :placeholder="match.participant1 ? (match.participant1.win || '0') : '0'"
                    >
                  </div>
                  <!-- 参赛者2 -->
                  <div class="participant" :class="{ winner: match.winner && match.participant2 && match.winner.id === match.participant2.id }">
                    {{ match.participant2 ? match.participant2.name : '轮空' }}
                    <input type="number" min="0" class="score-input"
                      v-model.number="match.score2"
                      :disabled="match.decided || !match.participant1 || !match.participant2"
                      :placeholder="match.participant2 ? (match.participant2.win || '0') : '0'"
                    >
                  </div>
                  <!-- 确认比分按钮 -->
                  <button class="score-btn"
                    :disabled="match.decided || !match.participant1 || !match.participant2"
                    @click="confirmScore(match)">
                    确认比分
                  </button>
                </div>
              </template>
            </div>
          </template>
        </div>
        <svg class="bracket-lines" id="bracketLines"></svg>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, watch, nextTick, onUnmounted } from 'vue';
import { getSignUpResultList, updateSignUpResult, getTournamentList } from '@/api/tournament';

const props = defineProps({
  tournamentId: {
    type: Number,
    required: true
  }
});

const tournaments = ref([]);
const selectedTournamentId = ref('');
const selectedTournamentName = ref('');
const participants = ref([]);
const loading = ref(false);
const finalRanking = ref(null);

const tournament = ref({
  id: props.tournamentId,
  name: '',
  participants: [],
  rounds: 0,
  matches: []
});

const canGenerateBracket = computed(() => {
  return selectedTournamentId.value && participants.value.length >= 2;
});

const roundsMatches = computed(() => {
  const arr = [];
  for (let r = 1; r <= tournament.value.rounds; r++) {
    arr.push(tournament.value.matches.filter(m => m.round === r));
  }
  return arr;
});

onMounted(() => {
  fetchTournamentList();
});

const fetchTournamentList = async () => {
  try {
    const data = await getTournamentList();
    tournaments.value = data;
  } catch (err) {
    console.error('获取比赛列表失败:', err);
  }
};

const handleTournamentChange = async () => {
  if (!selectedTournamentId.value) {
    selectedTournamentName.value = '';
    participants.value = [];
    tournament.value.id = null;
    tournament.value.name = '';
    tournament.value.participants = [];
    return;
  }

  const selectedTournament = tournaments.value.find(t => t.id === selectedTournamentId.value);
  if (selectedTournament) {
    selectedTournamentName.value = selectedTournament.name;
    tournament.value.id = selectedTournamentId.value;
    tournament.value.name = selectedTournament.name;
    loading.value = true;

    try {
      const data = await getSignUpResultList();
      const filtered = data.filter(item => item.tournament_id == selectedTournamentId.value);
      participants.value = filtered.map(item => ({ id: item.id, name: item.sign_name }));
      tournament.value.participants = participants.value;
    } catch (err) {
      console.error('获取参赛者失败:', err);
    } finally {
      loading.value = false;
    }
  }
};

const generateBracket = () => {
  if (!canGenerateBracket.value) return;
  finalRanking.value = null;
  generateSingleEliminationBracket();
  nextTick(() => drawConnections());
};

const generateSingleEliminationBracket = async () => {
  tournament.value.matches = [];
  tournament.value.rounds = Math.ceil(Math.log2(tournament.value.participants.length));
  const totalPlayers = Math.pow(2, tournament.value.rounds);
  const shuffled = [...tournament.value.participants].sort(() => Math.random() - 0.5);

  const latestData = await getSignUpResultList();
  const filteredData = latestData.filter(item => item.tournament_id == tournament.value.id);

  while (shuffled.length < totalPlayers) {
    shuffled.push(null);
  }

  // 生成第一轮比赛
  const firstRoundMatchesCount = totalPlayers / 2;
  for (let i = 0; i < firstRoundMatchesCount; i++) {
    const p1 = shuffled[i * 2];
    const p2 = shuffled[i * 2 + 1];
    let winner = null;
    let decided = false;

    if (p1 && !p2) { // p1 gets a bye
      winner = p1;
      decided = true;
    } else if (!p1 && p2) { // p2 gets a bye
      winner = p2;
      decided = true;
    } else if (!p1 && !p2) { // double bye
      winner = null; // Winner is null for a double bye
      decided = true;
    }
    // If p1 && p2, winner is null, decided is false (normal match)

    const p1Latest = p1 ? filteredData.find(item => item.id === p1.id) : null;
    const p2Latest = p2 ? filteredData.find(item => item.id === p2.id) : null;

    tournament.value.matches.push({
      id: `${1}-${i + 1}`,
      round: 1,
      matchNumber: i + 1,
      participant1: p1,
      participant2: p2,
      winner,
      score1: decided && winner === p1 ? 1 : (p1Latest?.win || 0), // Score 1 for bye winner, else existing or 0
      score2: decided && winner === p2 ? 1 : (p2Latest?.win || 0), // Score 1 for bye winner, else existing or 0
      decided,
      // participantXResolved flags are not needed for round 1 matches as they are resolved by definition or play
    });
  }

  // 生成后续轮次
  for (let r = 2; r <= tournament.value.rounds; r++) {
    const matchCount = totalPlayers / Math.pow(2, r);
    for (let i = 0; i < matchCount; i++) {
      tournament.value.matches.push({
        id: `${r}-${i + 1}`,
        round: r,
        matchNumber: i + 1,
        participant1: null, // Placeholder, will be filled by previous round's winner
        participant2: null, // Placeholder
        participant1Resolved: false, // New flag
        participant2Resolved: false, // New flag
        winner: null,
        score1: null,
        score2: null,
        decided: false
      });
    }
  }

  // 处理第一轮中的轮空晋级
  const firstRoundActualMatches = tournament.value.matches.filter(m => m.round === 1);
  for (const match of firstRoundActualMatches) {
    if (match.decided) { // If the match was decided (bye, double bye)
      updateNextRound(match); // Propagate its result (winner could be player or null)
    }
  }
};

const drawConnections = () => {
  try {
    const bracketLinesSVG = document.getElementById('bracketLines');
    const bracketDiv = document.getElementById('bracket');
    if (!bracketDiv || !bracketLinesSVG) return;
    bracketLinesSVG.innerHTML = '';
    const bracketRect = bracketDiv.getBoundingClientRect();
    const matchElements = {};
    document.querySelectorAll('.match').forEach(el => {
      const id = el.id.replace('match-', '');
      matchElements[id] = el;
    });
    tournament.value.matches.forEach(match => {
      if (match.round === tournament.value.rounds) return;
      if (!match.decided) return;
      const nextRound = match.round + 1;
      const nextMatchNumber = Math.floor((match.matchNumber - 1) / 2) + 1;
      const nextMatchId = `${nextRound}-${nextMatchNumber}`;
      const nextMatchEl = matchElements[nextMatchId];
      const currentMatchEl = matchElements[match.id];
      if (!nextMatchEl || !currentMatchEl) return;
      const winnerIndex = (match.winner.id === (match.participant1 && match.participant1.id)) ? 1 : 2;
      const curRect = currentMatchEl.getBoundingClientRect();
      const nextRect = nextMatchEl.getBoundingClientRect();
      const startX = curRect.right - bracketRect.left;
      const startY = curRect.top - bracketRect.top + (winnerIndex === 1 ? 20 : 50);
      const endX = nextRect.left - bracketRect.left;
      const endY = nextRect.top - bracketRect.top + (match.matchNumber % 2 === 1 ? 20 : 50);
      const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
      path.setAttribute('stroke', '#666');
      path.setAttribute('fill', 'none');
      path.setAttribute('stroke-width', '2');
      const midX = (startX + endX) / 2;
      const d = `M${startX},${startY} L${midX},${startY} L${midX},${endY} L${endX},${endY}`;
      path.setAttribute('d', d);
      bracketLinesSVG.appendChild(path);
    });
  } catch (e) {
    console.warn('drawConnections error:', e);
  }
};

onUnmounted(() => {
  const bracketLinesSVG = document.getElementById('bracketLines');
  if (bracketLinesSVG) bracketLinesSVG.innerHTML = '';
});

const emit = defineEmits(['refreshPlayers']);

async function confirmScore(match) {
  const s1 = Number(match.score1);
  const s2 = Number(match.score2);
  if (isNaN(s1) || isNaN(s2)) {
    alert('请输入有效的比分');
    return;
  }
  if (s1 === s2) {
    alert('比分不能平局');
    return;
  }
  match.score1 = s1;
  match.score2 = s2;
  match.winner = s1 > s2 ? match.participant1 : match.participant2;
  match.decided = true;
  updateNextRound(match);
  // 重新绘制连线
  nextTick(() => drawConnections());
  if (match.round === tournament.value.rounds) {
    calculateFinalRanking();
  }

  // 新增：同步胜负到API
  const p1 = match.participant1;
  const p2 = match.participant2;
  try {
    if (p1 && p2) {
      // 先获取最新的报名数据
      const latestData = await getSignUpResultList();
      const p1Latest = latestData.find(item => item.id === p1.id);
      const p2Latest = latestData.find(item => item.id === p2.id);

      // 补全字段，使用最新的API数据
      const p1Data = {
        tournament_id: tournament.value.id,
        tournament_name: tournament.value.name,
        team_name: p1.team_name || '',
        sign_name: p1.name || p1.sign_name || '',
        win: String(Number(p1Latest?.win || 0) + s1),
        lose: String(Number(p1Latest?.lose || 0) + s2),
        status: s1 > s2 ? 'win' : 'lose',
        qq_code: p1.qq_code || p1.qq || ''
      };
      const p2Data = {
        tournament_id: tournament.value.id,
        tournament_name: tournament.value.name,
        team_name: p2.team_name || '',
        sign_name: p2.name || p2.sign_name || '',
        win: String(Number(p2Latest?.win || 0) + s2),
        lose: String(Number(p2Latest?.lose || 0) + s1),
        status: s2 > s1 ? 'win' : 'lose',
        qq_code: p2.qq_code || p2.qq || ''
      };
      await updateSignUpResult(p1.id, p1Data);
      await updateSignUpResult(p2.id, p2Data);
      // 刷新报名数据和赛程
      await handleTournamentChange();
      // 强制同步 participants 和 tournament.value.participants
      participants.value = [...participants.value];
      tournament.value.participants = [...participants.value];
    }
  } catch (err) {
    alert('更新数据失败');
    console.error(err);
  }

  emit('refreshPlayers');
}

const updateNextRound = (currentDecidedMatch) => {
  if (!currentDecidedMatch.decided) { // Winner can be null (e.g. double bye)
    console.warn("updateNextRound called on non-decided match", currentDecidedMatch);
    return;
  }

  if (currentDecidedMatch.round === tournament.value.rounds) {
    return; // This was the final match or a match in the final round
  }

  const nextRound = currentDecidedMatch.round + 1;
  const nextMatchIndexInRound = Math.floor((currentDecidedMatch.matchNumber - 1) / 2);
  const nextMatch = tournament.value.matches.find(m => m.round === nextRound && m.matchNumber === nextMatchIndexInRound + 1);

  if (!nextMatch) {
    console.error("Could not find next match for", currentDecidedMatch);
    return;
  }

  const isFeederForParticipant1 = (currentDecidedMatch.matchNumber - 1) % 2 === 0;

  if (isFeederForParticipant1) {
    nextMatch.participant1 = currentDecidedMatch.winner; // Winner might be null
    nextMatch.participant1Resolved = true;
  } else {
    nextMatch.participant2 = currentDecidedMatch.winner; // Winner might be null
    nextMatch.participant2Resolved = true;
  }

  // Only proceed if both participant slots for nextMatch are resolved
  if (nextMatch.participant1Resolved && nextMatch.participant2Resolved) {
    const p1 = nextMatch.participant1;
    const p2 = nextMatch.participant2;

    if (p1 && !p2) { // p1 advances due to p2 being a bye (null)
      nextMatch.winner = p1;
      nextMatch.score1 = 1; // Convention for bye win
      nextMatch.score2 = 0;
      nextMatch.decided = true;
    } else if (!p1 && p2) { // p2 advances due to p1 being a bye (null)
      nextMatch.winner = p2;
      nextMatch.score1 = 0;
      nextMatch.score2 = 1; // Convention for bye win
      nextMatch.decided = true;
    } else if (!p1 && !p2) { // Double bye in this nextMatch
      nextMatch.winner = null; // No winner advances
      nextMatch.score1 = 0;
      nextMatch.score2 = 0;
      nextMatch.decided = true; // This "match" is decided as a double bye
    } else if (p1 && p2) { // Both participants are actual players, match is ready to be played
      nextMatch.winner = null;
      nextMatch.score1 = null; // Or 0, depending on display preference for undecided matches
      nextMatch.score2 = null; // Or 0
      nextMatch.decided = false;
    } else {
      // This case should ideally not be reached if logic is correct
      console.warn("Unexpected state in updateNextRound for nextMatch:", nextMatch);
      nextMatch.decided = false; // Default to not decided to prevent erroneous propagation
    }

    // If nextMatch itself was decided (due to byes), propagate its result further
    if (nextMatch.decided) {
      updateNextRound(nextMatch);
    }
  }
  // If only one participant is resolved, wait for the other feeder match to complete.
};

const calculateFinalRanking = () => {
  const finalMatch = tournament.value.matches.find(m => m.round === tournament.value.rounds);
  if (!finalMatch || !finalMatch.winner) return;

  const champion = finalMatch.winner;
  const runnerUp = finalMatch.participant1 && finalMatch.participant2
    ? (finalMatch.winner.id === finalMatch.participant1.id ? finalMatch.participant2 : finalMatch.participant1)
    : null;

  let semiFinalMatches = tournament.value.matches.filter(m => m.round === tournament.value.rounds - 1);
  let semiFinalLosers = [];
  semiFinalMatches.forEach(m => {
    if (m.decided && m.winner) {
      const loser = (m.participant1 && m.participant1.id !== m.winner.id) ? m.participant1 : m.participant2;
      if (loser) semiFinalLosers.push(loser);
    }
  });

  finalRanking.value = {
    champion: champion.name,
    runnerUp: runnerUp ? runnerUp.name : '未知',
    thirdPlace: semiFinalLosers.length > 0 ? semiFinalLosers[0].name : '未知'
  };
};

// 监听赛程变化自动重绘连线
watch(roundsMatches, () => {
  nextTick(() => drawConnections());
});
</script>

<style>
.tournament-bracket-root {
  font-family: Arial, sans-serif;
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.tournament-bracket-root * {
  box-sizing: border-box;
}

.tournament-bracket-root ul {
  padding-left: 20px;
  margin: 0 0 10px 0;
}

.tournament-bracket-root li {
  margin-bottom: 4px;
  list-style: disc;
}

.tournament-bracket-root button {
  outline: none;
}

.tournament-bracket-root input[type=number]::-webkit-inner-spin-button,
.tournament-bracket-root input[type=number]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.tournament-bracket-root input[type=number] {
  -moz-appearance: textfield;
}

.tournament-bracket-root h1 {
  text-align: center;
}

.tournament-bracket-root .container {
  display: flex;
  gap: 20px;
  align-items: flex-start;
  min-height: 500px;
}

.tournament-bracket-root .control-panel {
  flex: 1;
  min-width: 280px;
  background: #f0f0f0;
  padding: 15px;
  border-radius: 6px;
  height: 100%;
  box-sizing: border-box;
}

.tournament-bracket-root .bracket-container {
  flex: 3;
  position: relative;
  overflow-x: auto;
  background: #fff;
  padding: 15px;
  border-radius: 6px;
  border: 1px solid #ccc;
  box-shadow: 0 2px 12px rgba(0,0,0,0.08);
  min-height: 400px;
  display: flex;
  align-items: flex-start;
}

.tournament-bracket-root .bracket {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 220px;
  gap: 40px 10px;
  position: relative;
  padding-bottom: 50px;
  min-width: 600px;
  min-height: 350px;
}

.tournament-bracket-root .round {
  display: grid;
  grid-auto-rows: 70px;
  gap: 20px;
}

.tournament-bracket-root .round-title {
  text-align: center;
  font-weight: bold;
  margin-bottom: 15px;
}

.tournament-bracket-root .match {
  background: #fafafa;
  border: 1px solid #ddd;
  border-radius: 6px;
  padding: 8px 12px;
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.1);
  position: relative;
  font-size: 14px;
}

.tournament-bracket-root .participant {
  display: flex;
  justify-content: space-between;
  margin-bottom: 6px;
  cursor: default;
  user-select: none;
}

.tournament-bracket-root .participant.winner {
  font-weight: bold;
  color: #2a7f2a;
}

.tournament-bracket-root .score-input {
  width: 40px;
  font-size: 14px;
  padding: 2px 4px;
  margin-left: 6px;
  border: 1px solid #aaa;
  border-radius: 3px;
}

.tournament-bracket-root .score-btn {
  margin-top: 4px;
  width: 100%;
  background: #007acc;
  border: none;
  color: white;
  font-weight: bold;
  padding: 6px 0;
  border-radius: 4px;
  cursor: pointer;
}

.tournament-bracket-root .score-btn:disabled {
  background: #aaa;
  cursor: not-allowed;
}

.tournament-bracket-root #finalRanking {
  margin-top: 15px;
  background: #fffbdb;
  border: 1px solid #f0e68c;
  padding: 12px;
  border-radius: 6px;
}

.tournament-bracket-root svg.bracket-lines {
  position: absolute;
  top: 40px;
  left: 0;
  pointer-events: none;
  overflow: visible;
  height: 100%;
  width: 100%;
}
.tournament-bracket-root svg.bracket-lines path {
  stroke: #666;
  fill: none;
  stroke-width: 2;
}

.tournament-bracket-root .tournament-info {
  margin-bottom: 15px;
  padding: 10px;
  background: #e6f7ff;
  border-radius: 4px;
}

.tournament-bracket-root .loading {
  color: #666;
  font-style: italic;
}

.tournament-bracket-root select {
  width: 100%;
  padding: 8px;
  margin-bottom: 10px;
  border-radius: 4px;
  border: 1px solid #ccc;
}
</style>