<template>
  <div class="app">
    <header class="app-header">
      <div>
        <p class="eyebrow">Music Jeopardy</p>
        <h1>Track the Beat, Claim the Points</h1>
      </div>
      <div v-if="step === 'game'" class="selector-pill">
        <span class="label">Selecting</span>
        <span class="value">{{ currentSelector?.name || '—' }}</span>
      </div>
    </header>

    <main class="app-main">
      <section v-if="step === 'setup'" class="panel">
        <h2>Team Setup</h2>
        <p class="hint">Add teams, name them, and create their color gradients.</p>

        <div class="teams-grid">
          <div v-for="team in teams" :key="team.id" class="team-card">
            <div class="team-card-header">
              <input
                v-model="team.name"
                class="input"
                placeholder="Team name"
              />
              <button class="ghost" @click="removeTeam(team.id)">Remove</button>
            </div>
            <div class="gradient-preview" :style="teamGradient(team)"></div>
            <div class="color-row">
              <label>
                Color A
                <input v-model="team.colorA" type="color" />
              </label>
              <label>
                Color B
                <input v-model="team.colorB" type="color" />
              </label>
            </div>
          </div>
          <button class="add-card" @click="addTeam">
            <span>+ Add Team</span>
          </button>
        </div>

        <div class="actions">
          <button class="primary" :disabled="!canProceed" @click="goToSelect">
            Next: Choose Game
          </button>
        </div>
      </section>

      <section v-if="step === 'select'" class="panel">
        <h2>Select a Game</h2>
        <p class="hint">
          Games are loaded from <code>src/Data</code>. Each subfolder becomes a
          playable game.
        </p>

        <div v-if="games.length === 0" class="empty-state">
          <p>No games found yet.</p>
          <p>
            Add folders in <code>src/Data/&lt;GameName&gt;/&lt;Category&gt;</code>
            with <code>Songs</code> and <code>Answers</code> subfolders.
          </p>
        </div>

        <div class="games-grid" v-else>
          <button
            v-for="game in games"
            :key="game.name"
            class="game-card"
            @click="startGame(game)"
          >
            <h3>{{ game.name }}</h3>
            <p>{{ game.categories.length }} categories</p>
          </button>
        </div>

        <div class="actions">
          <button class="ghost" @click="step = 'setup'">Back</button>
        </div>
      </section>

      <section v-if="step === 'game'" class="game-layout">
        <aside class="scoreboard">
          <h2>Teams</h2>
          <div class="team-list">
            <button
              v-for="team in teams"
              :key="team.id"
              class="team-score-card"
              :class="{ active: team.id === currentSelectorId }"
              :style="teamGradient(team)"
              @click="awardPoints(team.id)"
              :disabled="!canAward"
            >
              <div class="team-name">{{ team.name }}</div>
              <div class="team-score">{{ team.score }}</div>
              <div v-if="team.id === lastAwardedTeamId" class="award-tag">
                Last Award
              </div>
            </button>
          </div>
          <div class="controls">
            <button class="ghost" @click="resetGame">Reset Game</button>
          </div>
        </aside>

        <section class="board">
          <div class="board-grid">
            <div
              v-for="(category, cIndex) in selectedGame?.categories || []"
              :key="category.name"
              class="category-column"
            >
              <div class="category-title">{{ category.name }}</div>
              <button
                v-for="(clue, qIndex) in category.clues"
                :key="clue.points"
                class="tile"
                :class="tileClass(cIndex, qIndex)"
                :style="tileStyle(cIndex, qIndex)"
                :disabled="tileDisabled(cIndex, qIndex)"
                @click="handleTileClick(cIndex, qIndex)"
                @contextmenu.prevent="handleTileRightClick(cIndex, qIndex)"
              >
                <span v-if="tileStatus(cIndex, qIndex) === 'available'">
                  {{ clue.points }}
                </span>
                <span v-else-if="tileStatus(cIndex, qIndex) === 'playing'">
                  Playing
                </span>
                <span v-else-if="tileStatus(cIndex, qIndex) === 'paused'">
                  Paused
                </span>
                <span v-else-if="tileStatus(cIndex, qIndex) === 'guessed'">
                  Guessed
                </span>
                <span v-else-if="tileStatus(cIndex, qIndex) === 'won'">
                  Won
                </span>
                <span v-else>Skipped</span>
              </button>
            </div>
          </div>

          <div class="player-panel">
            <div class="player-header">
              <h3>Now Playing</h3>
              <p>
                Left click the active tile to pause/guess. Right click to resume
                or skip.
              </p>
            </div>
            <div class="player-body">
              <audio
                ref="player"
                v-if="currentClipUrl"
                :src="currentClipUrl"
                controls
              ></audio>
              <div v-else class="player-empty">
                Pick a tile to start the round.
              </div>
            </div>
          </div>
        </section>
      </section>

      <section v-if="step === 'end'" class="panel end-panel">
        <h2>Final Scores</h2>
        <div class="winner-banner">
          <span>Winner</span>
          <strong>{{ winnerNames }}</strong>
        </div>
        <div class="teams-grid">
          <div
            v-for="team in teams"
            :key="team.id"
            class="team-card"
            :class="{ winner: winnerIds.includes(team.id) }"
          >
            <div class="gradient-preview" :style="teamGradient(team)"></div>
            <h3>{{ team.name }}</h3>
            <p class="score">{{ team.score }} pts</p>
          </div>
        </div>
        <div class="actions">
          <button class="primary" @click="step = 'setup'">
            Start New Game
          </button>
        </div>
      </section>
    </main>
  </div>
</template>

<script lang="ts">
import { nextTick } from 'vue'
import { gameData, type Game } from './dataLoader'

type Team = {
  id: string
  name: string
  colorA: string
  colorB: string
  score: number
}

type TileEntry = {
  status: 'available' | 'playing' | 'paused' | 'guessed' | 'won' | 'void'
  lastTeamId: string | null
}

type TileMap = Record<string, TileEntry>

const makeTeam = (index: number): Team => ({
  id: `team-${Date.now()}-${index}`,
  name: `Team ${index + 1}`,
  colorA: '#3dd6ff',
  colorB: '#fbd72b',
  score: 0
})

export default {
  data() {
    return {
      step: 'setup',
      teams: [makeTeam(0), makeTeam(1)] as Team[],
      games: gameData as Game[],
      selectedGame: null as Game | null,
      tiles: {} as TileMap,
      currentTileKey: null,
      currentClipUrl: '',
      currentSelectorId: null,
      lastAwardedTeamId: null
    }
  },
  computed: {
    canProceed() {
      return this.teams.length > 0 && this.teams.every((team) => team.name.trim())
    },
    currentSelector() {
      return this.teams.find((team) => team.id === this.currentSelectorId) || null
    },
    canAward() {
      return !!this.currentTileKey && this.tiles[this.currentTileKey]?.status === 'guessed'
    },
    winnerIds() {
      const maxScore = Math.max(...this.teams.map((team) => team.score))
      return this.teams.filter((team) => team.score === maxScore).map((team) => team.id)
    },
    winnerNames() {
      return this.teams
        .filter((team) => this.winnerIds.includes(team.id))
        .map((team) => team.name)
        .join(', ')
    }
  },
  methods: {
    getPlayer() {
      return this.$refs.player as HTMLAudioElement | undefined
    },
    teamGradient(team: Team) {
      return {
        background: `linear-gradient(135deg, ${team.colorA}, ${team.colorB})`
      }
    },
    addTeam() {
      this.teams.push(makeTeam(this.teams.length))
    },
    removeTeam(id: string) {
      if (this.teams.length === 1) return
      this.teams = this.teams.filter((team) => team.id !== id)
    },
    goToSelect() {
      this.step = 'select'
    },
    startGame(game: Game) {
      this.selectedGame = game
      this.tiles = {}
      this.currentTileKey = null
      this.currentClipUrl = ''
      this.lastAwardedTeamId = null
      this.teams = this.teams.map((team) => ({ ...team, score: 0 }))
      const randomTeam = this.teams[Math.floor(Math.random() * this.teams.length)]
      this.currentSelectorId = randomTeam?.id || null
      this.step = 'game'
    },
    resetGame() {
      this.step = 'select'
      this.selectedGame = null
      this.tiles = {}
      this.currentTileKey = null
      this.currentClipUrl = ''
      this.lastAwardedTeamId = null
    },
    tileKey(cIndex: number, qIndex: number) {
      return `${cIndex}-${qIndex}`
    },
    tileStatus(cIndex: number, qIndex: number) {
      const key = this.tileKey(cIndex, qIndex)
      return this.tiles[key]?.status || 'available'
    },
    tileDisabled(cIndex: number, qIndex: number) {
      const status = this.tileStatus(cIndex, qIndex)
      if (status === 'won' || status === 'void') return true
      if (!this.currentTileKey) return false
      return this.currentTileKey !== this.tileKey(cIndex, qIndex)
    },
    tileClass(cIndex: number, qIndex: number) {
      const status = this.tileStatus(cIndex, qIndex)
      return {
        playing: status === 'playing',
        paused: status === 'paused',
        guessed: status === 'guessed',
        won: status === 'won',
        void: status === 'void'
      }
    },
    tileStyle(cIndex: number, qIndex: number) {
      const key = this.tileKey(cIndex, qIndex)
      const entry = this.tiles[key]
      if (entry?.status !== 'won' || !entry.lastTeamId) return {}
      const team = this.teams.find((t) => t.id === entry.lastTeamId)
      if (!team) return {}
      return this.teamGradient(team)
    },
    async handleTileClick(cIndex: number, qIndex: number) {
      const key = this.tileKey(cIndex, qIndex)
      const status = this.tileStatus(cIndex, qIndex)
      const clue = this.selectedGame?.categories[cIndex].clues[qIndex]

      if (!clue || !clue.song) return

      if (status === 'available') {
        this.tiles[key] = { status: 'playing', lastTeamId: null }
        this.currentTileKey = key
        this.currentClipUrl = encodeURI(clue.song)
        await nextTick()
        const player = this.getPlayer()
        if (player) {
          player.currentTime = 0
          player.load()
          player.play().catch(() => {})
        }
        return
      }

      if (status === 'playing') {
        this.tiles[key].status = 'paused'
        const player = this.getPlayer()
        player?.pause()
        return
      }

      if (status === 'paused') {
        this.tiles[key].status = 'guessed'
        this.lastAwardedTeamId = null
        if (clue.answer) {
          this.currentClipUrl = encodeURI(clue.answer)
          await nextTick()
          const player = this.getPlayer()
          if (player) {
            player.currentTime = 0
            player.load()
            player.play().catch(() => {})
          }
        }
        return
      }

      if (status === 'guessed') {
        if (!this.lastAwardedTeamId) return
        this.tiles[key].status = 'won'
        this.tiles[key].lastTeamId = this.lastAwardedTeamId
        this.currentSelectorId = this.lastAwardedTeamId
        this.currentTileKey = null
        this.currentClipUrl = ''
        this.lastAwardedTeamId = null
        this.checkEnd()
      }
    },
    handleTileRightClick(cIndex: number, qIndex: number) {
      const key = this.tileKey(cIndex, qIndex)
      const status = this.tileStatus(cIndex, qIndex)
      if (key !== this.currentTileKey) return

      if (status === 'paused') {
        this.tiles[key].status = 'playing'
        const player = this.getPlayer()
        player?.play().catch(() => {})
        return
      }

      if (status === 'playing') {
        this.tiles[key].status = 'void'
        this.currentTileKey = null
        this.currentClipUrl = ''
        const player = this.getPlayer()
        player?.pause()
        this.checkEnd()
      }
    },
    awardPoints(teamId: string) {
      if (!this.canAward) return
      const key = this.currentTileKey
      if (!key || !this.selectedGame) return
      const [cIndex, qIndex] = key.split('-').map(Number)
      const clue = this.selectedGame.categories[cIndex].clues[qIndex]
      this.teams = this.teams.map((team) =>
        team.id === teamId ? { ...team, score: team.score + clue.points } : team
      )
      this.lastAwardedTeamId = teamId
      if (this.tiles[key]) {
        this.tiles[key].lastTeamId = teamId
      }
    },
    checkEnd() {
      if (!this.selectedGame) return
      const allTiles: TileEntry['status'][] = []
      this.selectedGame.categories.forEach((category, cIndex) => {
        category.clues.forEach((_, qIndex) => {
          allTiles.push(this.tileStatus(cIndex, qIndex))
        })
      })
      const finished = allTiles.every((status) => status === 'won' || status === 'void')
      if (finished) {
        this.step = 'end'
      }
    }
  }
}
</script>
