<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import draggable from 'vuedraggable'
import type { SbaPlayer, LineupPlayerRequest, SubmitLineupsRequest } from '~/types'
import ActionButton from '~/components/UI/ActionButton.vue'

// Props
const props = defineProps<{
  gameId: string
  teamId?: number | null // Optional: if provided, user manages this team
}>()

const router = useRouter()
const config = useRuntimeConfig()

// Game and team data
const homeTeamId = ref<number | null>(null)
const awayTeamId = ref<number | null>(null)
const season = ref(3)

// Active tab (home or away)
type TeamTab = 'home' | 'away'
const activeTab = ref<TeamTab>('away') // Away bats first

// Search and filter state
const searchQuery = ref('')
type PositionFilter = 'all' | 'batters' | 'pitchers'
const positionFilter = ref<PositionFilter>('all')

// Player preview modal
const previewPlayer = ref<SbaPlayer | null>(null)
const showPreview = ref(false)

// Roster data
const homeRoster = ref<SbaPlayer[]>([])
const awayRoster = ref<SbaPlayer[]>([])
const loadingRoster = ref(false)
const submittingLineups = ref(false)

// Per-team submission state
const homeSubmitted = ref(false)
const awaySubmitted = ref(false)
const submittingHome = ref(false)
const submittingAway = ref(false)

// Lineup state - 10 slots each (1-9 batting, 10 pitcher)
interface LineupSlot {
  player: SbaPlayer | null
  position: string | null
  battingOrder: number | null // 1-9 for batters, null for pitcher
}

const homeLineup = ref<LineupSlot[]>(Array(10).fill(null).map((_, i) => ({
  player: null,
  position: null,
  battingOrder: i < 9 ? i + 1 : null // Slots 0-8 are batting order 1-9, slot 9 is pitcher
})))

const awayLineup = ref<LineupSlot[]>(Array(10).fill(null).map((_, i) => ({
  player: null,
  position: null,
  battingOrder: i < 9 ? i + 1 : null
})))

// Available roster for dragging (players not in lineup)
const availableHomeRoster = computed(() => {
  const usedPlayerIds = new Set(homeLineup.value.filter(s => s.player).map(s => s.player!.id))
  return homeRoster.value.filter(p => !usedPlayerIds.has(p.id))
})

const availableAwayRoster = computed(() => {
  const usedPlayerIds = new Set(awayLineup.value.filter(s => s.player).map(s => s.player!.id))
  return awayRoster.value.filter(p => !usedPlayerIds.has(p.id))
})

// Current lineup based on active tab
const currentLineup = computed(() => activeTab.value === 'home' ? homeLineup.value : awayLineup.value)
const currentRoster = computed(() => activeTab.value === 'home' ? availableHomeRoster.value : availableAwayRoster.value)

// Position category helpers (defined early for validation)
const PITCHER_POSITIONS = ['P', 'SP', 'RP', 'CP']

// Slot 10 (pitcher) should be disabled if a pitcher is in batting order
const pitcherSlotDisabled = computed(() => {
  const lineup = currentLineup.value
  return lineup.slice(0, 9).some(slot => slot.position && PITCHER_POSITIONS.includes(slot.position))
})

// Validation
const duplicatePositions = computed(() => {
  const lineup = currentLineup.value
  const positionCounts = new Map<string, number>()

  lineup.forEach(slot => {
    if (slot.player && slot.position) {
      positionCounts.set(slot.position, (positionCounts.get(slot.position) || 0) + 1)
    }
  })

  return Array.from(positionCounts.entries())
    .filter(([_, count]) => count > 1)
    .map(([pos, _]) => pos)
})

// Per-team validation
const homeValidationErrors = computed(() => validateLineup(homeLineup.value, 'Home'))
const awayValidationErrors = computed(() => validateLineup(awayLineup.value, 'Away'))

const validationErrors = computed(() => {
  // Show errors for active tab only
  if (activeTab.value === 'home') {
    return homeValidationErrors.value
  }
  return awayValidationErrors.value
})

function validateLineup(lineup: LineupSlot[], teamName: string): string[] {
  const errors: string[] = []

  // Check if a pitcher is in batting order (no DH game)
  const pitcherInBattingOrder = lineup.slice(0, 9).some(s => s.position && PITCHER_POSITIONS.includes(s.position))
  const requiredSlots = pitcherInBattingOrder ? 9 : 10

  // Check if all slots filled
  const filledSlots = lineup.filter(s => s.player).length
  if (filledSlots < requiredSlots) {
    errors.push(`${teamName}: Fill all ${requiredSlots} lineup slots`)
  }

  // Check for missing positions
  const missingPositions = lineup.filter(s => s.player && !s.position).length
  if (missingPositions > 0) {
    errors.push(`${teamName}: ${missingPositions} player${missingPositions > 1 ? 's' : ''} missing position`)
  }

  // Check for duplicate positions
  const positionCounts = new Map<string, number>()
  lineup.forEach(slot => {
    if (slot.player && slot.position) {
      positionCounts.set(slot.position, (positionCounts.get(slot.position) || 0) + 1)
    }
  })

  const duplicates = Array.from(positionCounts.entries())
    .filter(([_, count]) => count > 1)
    .map(([pos, _]) => pos)

  if (duplicates.length > 0) {
    errors.push(`${teamName}: Duplicate positions - ${duplicates.join(', ')}`)
  }

  return errors
}

// Per-team submit availability
const canSubmitHome = computed(() => homeValidationErrors.value.length === 0 && !homeSubmitted.value)
const canSubmitAway = computed(() => awayValidationErrors.value.length === 0 && !awaySubmitted.value)

// For active tab
const canSubmitActiveTeam = computed(() => {
  if (activeTab.value === 'home') {
    return canSubmitHome.value
  }
  return canSubmitAway.value
})

const isActiveTeamSubmitted = computed(() => {
  return activeTab.value === 'home' ? homeSubmitted.value : awaySubmitted.value
})

const isSubmittingActiveTeam = computed(() => {
  return activeTab.value === 'home' ? submittingHome.value : submittingAway.value
})

const canSubmit = computed(() => {
  return homeValidationErrors.value.length === 0 && awayValidationErrors.value.length === 0
})

// Get player's available positions
function getPlayerPositions(player: SbaPlayer): string[] {
  const positions: string[] = []
  for (let i = 1; i <= 8; i++) {
    const pos = player[`pos_${i}` as keyof SbaPlayer]
    if (pos && typeof pos === 'string') {
      positions.push(pos)
    }
  }
  // Always add DH as an option for all players
  if (!positions.includes('DH')) {
    positions.push('DH')
  }
  return positions
}

// Vuedraggable configuration
const dragOptions = {
  animation: 200,
  ghostClass: 'drag-ghost',
  chosenClass: 'drag-chosen',
  dragClass: 'drag-dragging',
  // Touch settings for mobile
  delay: 50,
  delayOnTouchOnly: true,
  touchStartThreshold: 3,
}

// Track which slot is being hovered during drag (for replacement mode visual)
const dragHoverSlot = ref<number | null>(null)
const isDragging = ref(false)

// Check if a slot is in "replacement mode" (occupied and being hovered)
function isReplacementMode(slotIndex: number): boolean {
  return isDragging.value && dragHoverSlot.value === slotIndex && !!currentLineup.value[slotIndex]?.player
}

// Get the player being replaced (for visual feedback)
function getReplacedPlayer(slotIndex: number): SbaPlayer | null {
  if (isReplacementMode(slotIndex)) {
    return currentLineup.value[slotIndex]?.player || null
  }
  return null
}

// Handle drag start - track that dragging is active
function handleDragStart() {
  isDragging.value = true
}

// Handle drag end - clear all drag state
function handleDragEnd() {
  isDragging.value = false
  dragHoverSlot.value = null
}

// Handle move event - fires when dragging over a slot
function handleSlotMove(evt: any, slotIndex: number) {
  dragHoverSlot.value = slotIndex
  // Always allow the move
  return true
}

// Handle mouse/touch leave on slot - clear hover state
function handleSlotLeave(slotIndex: number) {
  if (dragHoverSlot.value === slotIndex) {
    dragHoverSlot.value = null
  }
}

// Clone player when dragging from roster (don't remove from roster)
function clonePlayer(player: SbaPlayer): SbaPlayer {
  return { ...player }
}

// Handle when a player is added to a batting slot from roster or another slot
function handleSlotAdd(slotIndex: number, event: any) {
  const lineup = activeTab.value === 'home' ? homeLineup.value : awayLineup.value
  const player = event.item?._underlying_vm_ || event.clone?._underlying_vm_

  if (!player) return

  // If slot already has a player, swap logic would be needed
  // But vuedraggable handles removal from source automatically for moves
  lineup[slotIndex].player = player

  // Auto-assign position
  if (slotIndex === 9) {
    lineup[slotIndex].position = 'P'
  } else {
    const availablePositions = getPlayerPositions(player)
    if (availablePositions.length > 0) {
      lineup[slotIndex].position = availablePositions[0]
    }
  }
}

// Handle when a player is removed from a slot (moved to another slot)
function handleSlotRemove(slotIndex: number) {
  const lineup = activeTab.value === 'home' ? homeLineup.value : awayLineup.value
  lineup[slotIndex].player = null
  lineup[slotIndex].position = null
}

// Reactive slot arrays for vuedraggable - each slot is an array of 0-1 players
// These are synced with the lineup slots via watchers
const homeSlotArrays = ref<SbaPlayer[][]>(Array(10).fill(null).map(() => []))
const awaySlotArrays = ref<SbaPlayer[][]>(Array(10).fill(null).map(() => []))

// Current slot arrays based on active tab
const currentSlotArrays = computed(() =>
  activeTab.value === 'home' ? homeSlotArrays.value : awaySlotArrays.value
)

// Get slot players array for vuedraggable
function getSlotPlayers(slotIndex: number): SbaPlayer[] {
  return currentSlotArrays.value[slotIndex]
}

// Sync slot arrays when lineup changes (e.g., from populateLineupsFromData)
// Modifies arrays in-place to preserve vuedraggable's reference
function syncSlotArraysFromLineup(lineup: LineupSlot[], slotArrays: SbaPlayer[][]) {
  lineup.forEach((slot, index) => {
    const currentArr = slotArrays[index]
    const shouldHavePlayer = !!slot.player

    // Check if sync is needed
    const currentPlayer = currentArr[0]
    const isSame = shouldHavePlayer
      ? (currentPlayer && currentPlayer.id === slot.player!.id)
      : (currentArr.length === 0)

    if (!isSame) {
      // Modify array in place to preserve vuedraggable's reference
      currentArr.length = 0
      if (slot.player) {
        currentArr.push(slot.player)
      }
    }
  })
}

// Watch lineup changes and sync to slot arrays
watch(homeLineup, (newLineup) => {
  syncSlotArraysFromLineup(newLineup, homeSlotArrays.value)
}, { deep: true, immediate: true })

watch(awayLineup, (newLineup) => {
  syncSlotArraysFromLineup(newLineup, awaySlotArrays.value)
}, { deep: true, immediate: true })

// Handle slot change event from vuedraggable
function handleSlotChange(slotIndex: number, event: any) {
  const lineup = activeTab.value === 'home' ? homeLineup.value : awayLineup.value
  const slotArrays = activeTab.value === 'home' ? homeSlotArrays.value : awaySlotArrays.value
  const slotArray = slotArrays[slotIndex]

  if (event.added) {
    // Get the newly added player (last in array if multiple)
    const addedPlayer = event.added.element as SbaPlayer

    // CRITICAL: Enforce single player per slot
    // If there are multiple players (dropped onto existing), keep only the new one
    if (slotArray.length > 1) {
      // Find and remove the old player(s), keeping only the newly added one
      const playersToRemove = slotArray.filter((p: SbaPlayer) => p.id !== addedPlayer.id)

      // Clear the array and add only the new player
      slotArray.length = 0
      slotArray.push(addedPlayer)

      console.log(`[LineupBuilder] Slot ${slotIndex}: Replaced ${playersToRemove.map((p: SbaPlayer) => p.name).join(', ')} with ${addedPlayer.name}`)
    }

    // Update the lineup slot with the new player
    lineup[slotIndex].player = addedPlayer

    // Auto-assign position
    if (slotIndex === 9) {
      lineup[slotIndex].position = 'P'
    } else {
      const availablePositions = getPlayerPositions(addedPlayer)
      if (availablePositions.length > 0) {
        lineup[slotIndex].position = availablePositions[0]
      }
    }
  }
  if (event.removed) {
    // Player was removed from this slot
    lineup[slotIndex].player = null
    lineup[slotIndex].position = null
  }
}

// Legacy drag handler (kept for desktop native drag-drop fallback)
function handleRosterDrag(player: SbaPlayer, toSlotIndex: number, fromSlotIndex?: number) {
  const lineup = activeTab.value === 'home' ? homeLineup.value : awayLineup.value

  // If dragging from another slot, swap or move
  if (fromSlotIndex !== undefined && fromSlotIndex !== toSlotIndex) {
    const fromSlot = lineup[fromSlotIndex]
    const toSlot = lineup[toSlotIndex]

    // Swap players
    const tempPlayer = toSlot.player
    const tempPosition = toSlot.position

    toSlot.player = fromSlot.player
    toSlot.position = fromSlot.position

    fromSlot.player = tempPlayer
    fromSlot.position = tempPosition
  } else if (fromSlotIndex === undefined) {
    // Adding from roster pool
    lineup[toSlotIndex].player = player

    // For pitcher slot (index 9), always use 'P'
    if (toSlotIndex === 9) {
      lineup[toSlotIndex].position = 'P'
    } else {
      // Auto-suggest first available position
      const availablePositions = getPlayerPositions(player)
      if (availablePositions.length > 0) {
        lineup[toSlotIndex].position = availablePositions[0]
      }
    }
  }
}

function removePlayer(slotIndex: number) {
  const lineup = activeTab.value === 'home' ? homeLineup.value : awayLineup.value
  lineup[slotIndex].player = null
  lineup[slotIndex].position = null
}

// Clear entire lineup for current team
function clearLineup() {
  const lineup = activeTab.value === 'home' ? homeLineup.value : awayLineup.value
  lineup.forEach((slot, index) => {
    slot.player = null
    slot.position = null
  })
}

function playerHasPositionInCategory(player: SbaPlayer, category: PositionFilter): boolean {
  if (category === 'all') return true

  const positions = getPlayerPositions(player)
  const isPitcher = positions.some(p => PITCHER_POSITIONS.includes(p))

  switch (category) {
    case 'pitchers':
      return isPitcher
    case 'batters':
      return !isPitcher
    default:
      return true
  }
}

// Filtered roster based on search and position filter
const filteredRoster = computed(() => {
  let roster = currentRoster.value

  // Apply search filter
  if (searchQuery.value.trim()) {
    const query = searchQuery.value.toLowerCase().trim()
    roster = roster.filter(p => p.name.toLowerCase().includes(query))
  }

  // Apply position filter
  if (positionFilter.value !== 'all') {
    roster = roster.filter(p => playerHasPositionInCategory(p, positionFilter.value))
  }

  return roster
})

// Count of players in current lineup
const currentLineupCount = computed(() => {
  return currentLineup.value.filter(s => s.player).length
})

// Pitcher slot helper (for TypeScript narrowing)
const pitcherPlayer = computed(() => currentLineup.value[9]?.player)

// Show player preview
function openPlayerPreview(player: SbaPlayer) {
  previewPlayer.value = player
  showPreview.value = true
}

function closePlayerPreview() {
  showPreview.value = false
  previewPlayer.value = null
}

// Get player preview image with fallback priority: headshot > vanity_card > null
function getPlayerPreviewImage(player: SbaPlayer): string | null {
  return player.headshot || player.vanity_card || null
}

// Get player avatar fallback - use first + last initials (e.g., "Alex Verdugo" -> "AV")
// Ignores common suffixes like Jr, Sr, II, III, IV
function getPlayerFallbackInitial(player: SbaPlayer): string {
  const suffixes = ['jr', 'jr.', 'sr', 'sr.', 'ii', 'iii', 'iv', 'v']
  const parts = player.name.trim().split(/\s+/).filter(
    part => !suffixes.includes(part.toLowerCase())
  )
  if (parts.length >= 2) {
    return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase()
  }
  return parts[0]?.charAt(0).toUpperCase() || '?'
}

// Fetch game data
async function fetchGameData() {
  try {
    const response = await fetch(`${config.public.apiUrl}/api/games/${props.gameId}`, {
      credentials: 'include'
    })
    const data = await response.json()
    homeTeamId.value = data.home_team_id
    awayTeamId.value = data.away_team_id
  } catch (error) {
    console.error('Failed to fetch game data:', error)
  }
}

// Fetch roster for a team
async function fetchRoster(teamId: number) {
  try {
    loadingRoster.value = true
    const response = await fetch(`${config.public.apiUrl}/api/teams/${teamId}/roster?season=${season.value}`, {
      credentials: 'include'
    })
    const data = await response.json()
    return data.players as SbaPlayer[]
  } catch (error) {
    console.error(`Failed to fetch roster for team ${teamId}:`, error)
    return []
  } finally {
    loadingRoster.value = false
  }
}

// Submit single team lineup
async function submitTeamLineup(team: 'home' | 'away') {
  const teamId = team === 'home' ? homeTeamId.value : awayTeamId.value
  const lineup = team === 'home' ? homeLineup.value : awayLineup.value
  const availableRoster = team === 'home' ? availableHomeRoster.value : availableAwayRoster.value
  const isSubmitting = team === 'home' ? submittingHome : submittingAway
  const submitted = team === 'home' ? homeSubmitted : awaySubmitted
  const canSubmitTeam = team === 'home' ? canSubmitHome.value : canSubmitAway.value

  if (!canSubmitTeam || isSubmitting.value || !teamId) return

  isSubmitting.value = true

  // Build starting lineup request
  const lineupRequest = lineup
    .filter(s => s.player)
    .map(s => ({
      player_id: s.player!.id,
      position: s.position!,
      batting_order: s.battingOrder
    }))

  // Build bench request (players not in starting lineup)
  const benchRequest = availableRoster.map(p => ({
    player_id: p.id
  }))

  const request = {
    team_id: teamId,
    lineup: lineupRequest,
    bench: benchRequest
  }

  console.log(`Submitting ${team} lineup:`, JSON.stringify(request, null, 2))

  try {
    const response = await fetch(`${config.public.apiUrl}/api/games/${props.gameId}/lineup`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(request),
      credentials: 'include'
    })

    if (!response.ok) {
      const error = await response.json()
      console.error(`${team} lineup submission error:`, error)

      // Handle Pydantic validation errors
      if (error.detail && Array.isArray(error.detail)) {
        const messages = error.detail.map((err: any) => {
          if (err.loc) {
            const location = err.loc.join(' -> ')
            return `${location}: ${err.msg}`
          }
          return err.msg || JSON.stringify(err)
        })
        throw new Error(`Validation errors:\n${messages.join('\n')}`)
      }

      throw new Error(typeof error.detail === 'string' ? error.detail : JSON.stringify(error.detail))
    }

    const result = await response.json()
    console.log(`${team} lineup submitted:`, result)

    // Mark as submitted
    submitted.value = true

    // If game started, emit event
    if (result.game_started) {
      emit('lineups-submitted', result)
    }
  } catch (error) {
    console.error(`Failed to submit ${team} lineup:`, error)
    alert(error instanceof Error ? error.message : `Failed to submit ${team} lineup`)
  } finally {
    isSubmitting.value = false
  }
}

// Submit active team's lineup
async function submitActiveTeamLineup() {
  await submitTeamLineup(activeTab.value)
}

// Submit lineups (legacy - both teams at once)
async function submitLineups() {
  if (!canSubmit.value || submittingLineups.value) return

  submittingLineups.value = true

  // Build request
  const homeLineupRequest: LineupPlayerRequest[] = homeLineup.value
    .filter(s => s.player)
    .map(s => ({
      player_id: s.player!.id,
      position: s.position!,
      batting_order: s.battingOrder
    }))

  const awayLineupRequest: LineupPlayerRequest[] = awayLineup.value
    .filter(s => s.player)
    .map(s => ({
      player_id: s.player!.id,
      position: s.position!,
      batting_order: s.battingOrder
    }))

  const request: SubmitLineupsRequest = {
    home_lineup: homeLineupRequest,
    away_lineup: awayLineupRequest
  }

  console.log('Submitting lineup request:', JSON.stringify(request, null, 2))

  try {
    const response = await fetch(`${config.public.apiUrl}/api/games/${props.gameId}/lineups`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(request),
      credentials: 'include'
    })

    if (!response.ok) {
      const error = await response.json()
      console.error('Lineup submission error:', error)

      // Handle Pydantic validation errors
      if (error.detail && Array.isArray(error.detail)) {
        const messages = error.detail.map((err: any) => {
          if (err.loc) {
            const location = err.loc.join(' -> ')
            return `${location}: ${err.msg}`
          }
          return err.msg || JSON.stringify(err)
        })
        throw new Error(`Validation errors:\n${messages.join('\n')}`)
      }

      throw new Error(typeof error.detail === 'string' ? error.detail : JSON.stringify(error.detail))
    }

    const result = await response.json()
    console.log('Lineups submitted:', result)

    // Emit event instead of navigating (parent component handles navigation)
    emit('lineups-submitted', result)
  } catch (error) {
    console.error('Failed to submit lineups:', error)
    alert(error instanceof Error ? error.message : 'Failed to submit lineups')
  } finally {
    submittingLineups.value = false
  }
}

// Emit events
const emit = defineEmits<{
  'lineups-submitted': [result: any]
}>()

// Initialize
// Stored lineup data from backend (populated before rosters load)
interface LineupPlayerInfo {
  player_id: number
  position: string
  batting_order: number | null
}
const pendingHomeLineup = ref<LineupPlayerInfo[]>([])
const pendingAwayLineup = ref<LineupPlayerInfo[]>([])

// Check lineup status from backend
async function checkLineupStatus() {
  try {
    const response = await fetch(`${config.public.apiUrl}/api/games/${props.gameId}/lineup-status`, {
      credentials: 'include'
    })
    if (response.ok) {
      const status = await response.json()
      console.log('[LineupBuilder] Lineup status:', status)

      // Update submitted state based on backend
      homeSubmitted.value = status.home_lineup_submitted
      awaySubmitted.value = status.away_lineup_submitted

      // Store team IDs if not already set
      if (!homeTeamId.value) homeTeamId.value = status.home_team_id
      if (!awayTeamId.value) awayTeamId.value = status.away_team_id

      // Store lineup data for populating after rosters load
      if (status.home_lineup) pendingHomeLineup.value = status.home_lineup
      if (status.away_lineup) pendingAwayLineup.value = status.away_lineup
    }
  } catch (error) {
    console.error('Failed to check lineup status:', error)
  }
}

// Populate lineup slots from stored lineup data (call after rosters load)
function populateLineupsFromData() {
  // Populate home lineup
  if (pendingHomeLineup.value.length > 0 && homeRoster.value.length > 0) {
    console.log('[LineupBuilder] Populating home lineup from saved data')
    for (const entry of pendingHomeLineup.value) {
      const player = homeRoster.value.find(p => p.id === entry.player_id)
      if (player) {
        // Determine slot index: batting_order 1-9 maps to slots 0-8, null (pitcher only) maps to slot 9
        const slotIndex = entry.batting_order ? entry.batting_order - 1 : 9
        if (slotIndex >= 0 && slotIndex < 10) {
          homeLineup.value[slotIndex] = {
            player,
            position: entry.position,
            battingOrder: entry.batting_order
          }
        }
      }
    }
  }

  // Populate away lineup
  if (pendingAwayLineup.value.length > 0 && awayRoster.value.length > 0) {
    console.log('[LineupBuilder] Populating away lineup from saved data')
    for (const entry of pendingAwayLineup.value) {
      const player = awayRoster.value.find(p => p.id === entry.player_id)
      if (player) {
        const slotIndex = entry.batting_order ? entry.batting_order - 1 : 9
        if (slotIndex >= 0 && slotIndex < 10) {
          awayLineup.value[slotIndex] = {
            player,
            position: entry.position,
            battingOrder: entry.batting_order
          }
        }
      }
    }
  }
}

onMounted(async () => {
  await fetchGameData()

  // Check if lineups already submitted (also gets lineup data if available)
  await checkLineupStatus()

  // Fetch rosters
  if (homeTeamId.value) {
    homeRoster.value = await fetchRoster(homeTeamId.value)
  }
  if (awayTeamId.value) {
    awayRoster.value = await fetchRoster(awayTeamId.value)
  }

  // Populate lineup slots from saved data (now that rosters are loaded)
  populateLineupsFromData()

  // If teamId prop is provided, switch to that team's tab
  if (props.teamId) {
    if (props.teamId === homeTeamId.value) {
      activeTab.value = 'home'
    } else if (props.teamId === awayTeamId.value) {
      activeTab.value = 'away'
    }
  }
})
</script>

<template>
  <div class="min-h-screen bg-gradient-to-b from-gray-900 via-gray-900 to-gray-950 text-white">
    <!-- Header Bar -->
    <div class="bg-gray-900/95 backdrop-blur-sm border-b border-gray-800">
      <div class="max-w-6xl mx-auto px-4 py-3">
        <div class="flex items-center justify-between">
          <div>
            <h1 class="text-xl font-bold">Build Your Lineup</h1>
            <p class="text-xs text-gray-500 hidden sm:block">Drag players to assign positions</p>
          </div>
          <div class="text-sm text-gray-400">
            Game #{{ gameId.slice(0, 8) }}
          </div>
        </div>
      </div>
    </div>

    <div class="max-w-6xl mx-auto p-4">
      <!-- Team Tabs -->
      <div class="flex gap-2 mb-6 bg-gray-800/50 p-1 rounded-xl inline-flex">
        <button
          :class="[
            'px-6 py-2.5 font-semibold rounded-lg transition-all duration-200',
            activeTab === 'away'
              ? 'bg-blue-600 text-white shadow-lg shadow-blue-600/25'
              : 'text-gray-400 hover:text-white hover:bg-gray-700/50'
          ]"
          @click="activeTab = 'away'"
        >
          Away
        </button>
        <button
          :class="[
            'px-6 py-2.5 font-semibold rounded-lg transition-all duration-200',
            activeTab === 'home'
              ? 'bg-blue-600 text-white shadow-lg shadow-blue-600/25'
              : 'text-gray-400 hover:text-white hover:bg-gray-700/50'
          ]"
          @click="activeTab = 'home'"
        >
          Home
        </button>
      </div>

      <!-- Loading state -->
      <div v-if="loadingRoster" class="py-12">
        <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
          <!-- Skeleton roster panel -->
          <div class="lg:col-span-1">
            <div class="bg-gray-800/50 rounded-xl p-4 animate-pulse">
              <div class="h-6 w-32 bg-gray-700 rounded mb-4" />
              <div class="h-10 w-full bg-gray-700 rounded-lg mb-3" />
              <div class="flex gap-1 mb-3">
                <div v-for="i in 5" :key="i" class="h-6 w-16 bg-gray-700 rounded-full" />
              </div>
              <div class="space-y-2">
                <div v-for="i in 6" :key="i" class="h-16 bg-gray-700 rounded-lg" />
              </div>
            </div>
          </div>
          <!-- Skeleton lineup panel -->
          <div class="lg:col-span-2">
            <div class="h-6 w-24 bg-gray-700 rounded mb-4 animate-pulse" />
            <div class="space-y-2">
              <div v-for="i in 9" :key="i" class="h-14 bg-gray-800/50 rounded-lg animate-pulse" />
            </div>
          </div>
        </div>
      </div>

      <!-- Main content -->
      <div v-else class="grid grid-cols-1 lg:grid-cols-3 gap-6">
        <!-- Roster Pool (Sticky on desktop) -->
        <div class="lg:col-span-1 order-2 lg:order-1">
          <div class="lg:sticky lg:top-20">
            <!-- Roster Panel Header -->
            <div class="bg-gray-800/80 backdrop-blur-sm rounded-t-xl border border-gray-700/50 border-b-0 px-4 py-3">
              <div class="flex items-center justify-between">
                <h2 class="text-lg font-bold text-white">Available Players</h2>
                <span class="text-xs font-medium text-gray-400 bg-gray-700/50 px-2 py-1 rounded-full">
                  {{ filteredRoster.length }}
                </span>
              </div>
            </div>

            <!-- Search & Filters -->
            <div class="bg-gray-800/60 backdrop-blur-sm border-x border-gray-700/50 px-4 py-3 space-y-3">
              <!-- Search Input -->
              <div class="relative">
                <span class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-500 text-sm">
                  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
                  </svg>
                </span>
                <input
                  v-model="searchQuery"
                  type="text"
                  placeholder="Search players..."
                  class="w-full bg-gray-900/50 border border-gray-600/50 rounded-lg pl-10 pr-4 py-2 text-white text-sm placeholder-gray-500 focus:outline-none focus:border-blue-500/50 focus:ring-1 focus:ring-blue-500/25 transition-all"
                />
              </div>

              <!-- Position Filter Tabs -->
              <div class="flex flex-wrap gap-1.5">
                <button
                  v-for="filter in (['all', 'batters', 'pitchers'] as PositionFilter[])"
                  :key="filter"
                  :class="[
                    'px-3 py-1.5 text-xs font-medium rounded-lg transition-all duration-200',
                    positionFilter === filter
                      ? 'bg-blue-600 text-white shadow-md shadow-blue-600/25'
                      : 'bg-gray-700/50 text-gray-400 hover:text-white hover:bg-gray-700'
                  ]"
                  @click="positionFilter = filter"
                >
                  {{ filter === 'all' ? 'All' : filter.charAt(0).toUpperCase() + filter.slice(1) }}
                </button>
              </div>
            </div>

            <!-- Roster List -->
            <div class="bg-gray-800/40 backdrop-blur-sm rounded-b-xl border border-gray-700/50 border-t-0 p-2 max-h-[calc(100vh-22rem)] overflow-y-auto scrollbar-thin scrollbar-thumb-gray-600 scrollbar-track-transparent select-none">
              <draggable
                :list="filteredRoster"
                :group="{ name: 'lineup', pull: 'clone', put: false }"
                :clone="clonePlayer"
                :sort="false"
                item-key="id"
                v-bind="dragOptions"
                class="space-y-1.5"
                @start="handleDragStart"
                @end="handleDragEnd"
              >
                <template #item="{ element: player }">
                  <div
                    class="bg-gray-700/60 hover:bg-gray-700 rounded-lg p-2.5 cursor-grab active:cursor-grabbing transition-all duration-150 flex items-center gap-3 group hover:shadow-md hover:shadow-black/20 border border-transparent hover:border-gray-600/50 select-none touch-manipulation"
                  >
                    <!-- Player Headshot -->
                    <div class="flex-shrink-0 relative">
                      <img
                        v-if="getPlayerPreviewImage(player)"
                        :src="getPlayerPreviewImage(player)!"
                        :alt="player.name"
                        class="w-10 h-10 rounded-full object-cover bg-gray-600 ring-2 ring-gray-600/50"
                        @error="(e) => (e.target as HTMLImageElement).style.display = 'none'"
                      />
                      <div v-else class="w-10 h-10 rounded-full bg-gradient-to-br from-gray-600 to-gray-700 flex items-center justify-center text-gray-300 text-sm font-bold ring-2 ring-gray-600/50">
                        {{ getPlayerFallbackInitial(player) }}
                      </div>
                    </div>

                    <!-- Player Info -->
                    <div class="flex-1 min-w-0">
                      <div class="font-medium text-white truncate text-sm">{{ player.name }}</div>
                      <div class="flex items-center gap-1 mt-0.5">
                        <span
                          v-for="pos in getPlayerPositions(player).filter(p => p !== 'DH').slice(0, 3)"
                          :key="pos"
                          class="text-[10px] font-medium text-gray-400 bg-gray-800/80 px-1.5 py-0.5 rounded"
                        >
                          {{ pos }}
                        </span>
                        <span v-if="getPlayerPositions(player).filter(p => p !== 'DH').length > 3" class="text-[10px] text-gray-500">
                          +{{ getPlayerPositions(player).filter(p => p !== 'DH').length - 3 }}
                        </span>
                        <span v-if="getPlayerPositions(player).filter(p => p !== 'DH').length === 0" class="text-[10px] text-gray-500">
                          DH
                        </span>
                      </div>
                    </div>

                    <!-- Info Button -->
                    <button
                      class="flex-shrink-0 w-7 h-7 rounded-full bg-gray-600/50 hover:bg-blue-600 text-gray-400 hover:text-white text-xs flex items-center justify-center opacity-0 group-hover:opacity-100 transition-all"
                      @click.stop="openPlayerPreview(player)"
                    >
                      <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
                      </svg>
                    </button>
                  </div>
                </template>
              </draggable>

              <!-- Empty state -->
              <div v-if="filteredRoster.length === 0" class="text-center py-8">
                <div class="text-gray-500 text-sm">
                  {{ currentRoster.length === 0 ? 'All players assigned to lineup' : 'No players match your search' }}
                </div>
                <button
                  v-if="searchQuery || positionFilter !== 'all'"
                  class="mt-2 text-xs text-blue-400 hover:text-blue-300 transition-colors"
                  @click="searchQuery = ''; positionFilter = 'all'"
                >
                  Clear filters
                </button>
              </div>
            </div>
          </div>
        </div>

        <!-- Lineup Slots -->
        <div class="lg:col-span-2 order-1 lg:order-2">
          <!-- Lineup Header with Clear Button -->
          <div class="flex items-center justify-between mb-4">
            <div class="flex items-center gap-3">
              <h2 class="text-lg font-bold text-white">Batting Order</h2>
              <div class="flex items-center gap-1.5 text-xs">
                <span class="text-gray-400">Progress:</span>
                <div class="w-24 h-2 bg-gray-700 rounded-full overflow-hidden">
                  <div
                    class="h-full bg-gradient-to-r from-blue-600 to-blue-500 transition-all duration-300"
                    :style="{ width: `${(currentLineupCount / (pitcherSlotDisabled ? 9 : 10)) * 100}%` }"
                  />
                </div>
                <span class="font-medium text-gray-300">{{ currentLineupCount }}/{{ pitcherSlotDisabled ? 9 : 10 }}</span>
              </div>
            </div>
            <button
              v-if="currentLineupCount > 0"
              class="flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium bg-red-900/30 hover:bg-red-900/50 text-red-400 hover:text-red-300 rounded-lg border border-red-800/50 transition-all"
              @click="clearLineup"
            >
              <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
              </svg>
              Clear
            </button>
          </div>

          <!-- Batting order slots (1-9) -->
          <div class="space-y-1.5 mb-6 select-none">
            <div
              v-for="(slot, index) in currentLineup.slice(0, 9)"
              :key="index"
              :class="[
                'bg-gray-800/60 backdrop-blur-sm rounded-lg border transition-all duration-200',
                slot.player ? 'border-gray-700/50' : 'border-gray-700/30',
                isReplacementMode(index) ? 'ring-2 ring-amber-500/50 border-amber-500/50' : ''
              ]"
            >
              <div class="flex items-center gap-3 p-2.5">
                <!-- Batting order number -->
                <div :class="[
                  'flex-shrink-0 w-8 h-8 rounded-lg flex items-center justify-center transition-colors',
                  isReplacementMode(index) ? 'bg-amber-900/50' : 'bg-gray-700/50'
                ]">
                  <span :class="[
                    'text-sm font-bold',
                    isReplacementMode(index) ? 'text-amber-400' : 'text-gray-400'
                  ]">{{ index + 1 }}</span>
                </div>

                <!-- Player slot - vuedraggable drop zone -->
                <draggable
                  :list="getSlotPlayers(index)"
                  :group="{ name: 'lineup', pull: true, put: true }"
                  item-key="id"
                  v-bind="dragOptions"
                  :class="[
                    'flex-1 min-w-0 min-h-[44px] slot-drop-zone',
                    isReplacementMode(index) ? 'replacement-mode' : ''
                  ]"
                  @change="(e: any) => handleSlotChange(index, e)"
                  @start="handleDragStart"
                  @end="handleDragEnd"
                  :move="(evt: any) => handleSlotMove(evt, index)"
                >
                  <template #item="{ element: player }">
                    <div
                      :class="[
                        'rounded-lg p-2 cursor-grab active:cursor-grabbing transition-all duration-150 flex items-center gap-2.5 group border select-none touch-manipulation',
                        isReplacementMode(index)
                          ? 'bg-amber-900/40 border-amber-600/50 opacity-60'
                          : 'bg-blue-900/50 hover:bg-blue-900/70 border-blue-700/30'
                      ]"
                    >
                      <!-- Player Headshot -->
                      <div class="flex-shrink-0">
                        <img
                          v-if="getPlayerPreviewImage(player)"
                          :src="getPlayerPreviewImage(player)!"
                          :alt="player.name"
                          class="w-9 h-9 rounded-full object-cover bg-gray-600 ring-2 ring-blue-600/30"
                          @error="(e) => (e.target as HTMLImageElement).style.display = 'none'"
                        />
                        <div v-else class="w-9 h-9 rounded-full bg-gradient-to-br from-blue-700 to-blue-800 flex items-center justify-center text-blue-200 text-sm font-bold ring-2 ring-blue-600/30">
                          {{ getPlayerFallbackInitial(player) }}
                        </div>
                      </div>

                      <!-- Player Info -->
                      <div class="flex-1 min-w-0">
                        <div class="font-medium text-white truncate text-sm">{{ player.name }}</div>
                        <div class="flex items-center gap-1 mt-0.5">
                          <span
                            v-for="pos in getPlayerPositions(player).filter(p => p !== 'DH').slice(0, 2)"
                            :key="pos"
                            class="text-[10px] font-medium text-blue-300/80 bg-blue-950/50 px-1.5 py-0.5 rounded"
                          >
                            {{ pos }}
                          </span>
                        </div>
                      </div>

                      <!-- Info Button -->
                      <button
                        class="flex-shrink-0 w-6 h-6 rounded-full bg-blue-800/50 hover:bg-blue-600 text-blue-300 hover:text-white text-xs flex items-center justify-center opacity-0 group-hover:opacity-100 transition-all"
                        @click.stop="openPlayerPreview(player)"
                      >
                        <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
                        </svg>
                      </button>

                      <!-- Remove Button -->
                      <button
                        class="flex-shrink-0 w-6 h-6 rounded-full bg-red-900/30 hover:bg-red-900/60 text-red-400 hover:text-red-300 text-xs flex items-center justify-center transition-all"
                        @click.stop="removePlayer(index)"
                      >
                        <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
                        </svg>
                      </button>
                    </div>
                  </template>
                  <template #footer>
                    <!-- Replacement indicator when dragging over occupied slot -->
                    <div
                      v-if="isReplacementMode(index)"
                      class="absolute inset-0 flex items-center justify-center bg-amber-900/20 rounded-lg pointer-events-none z-10"
                    >
                      <span class="text-xs font-medium text-amber-400 bg-amber-950/80 px-2 py-1 rounded">
                        Replacing {{ getReplacedPlayer(index)?.name }}
                      </span>
                    </div>
                    <!-- Empty slot placeholder -->
                    <div v-else-if="!slot.player" class="border-2 border-dashed border-gray-600/50 rounded-lg py-3 px-4 text-center text-gray-500 text-xs transition-colors hover:border-gray-500/50 hover:bg-gray-800/30">
                      Drop player here
                    </div>
                  </template>
                </draggable>

                <!-- Position selector -->
                <div class="w-20 flex-shrink-0">
                  <select
                    v-if="slot.player"
                    v-model="slot.position"
                    :class="[
                      'w-full bg-gray-700/80 border rounded-lg px-2 py-1.5 text-sm font-medium transition-all focus:outline-none focus:ring-1',
                      duplicatePositions.includes(slot.position || '')
                        ? 'border-red-500 text-red-400 focus:ring-red-500/50'
                        : 'border-gray-600/50 text-white focus:border-blue-500/50 focus:ring-blue-500/25'
                    ]"
                  >
                    <option :value="null" class="text-gray-400">Pos</option>
                    <option
                      v-for="pos in getPlayerPositions(slot.player)"
                      :key="pos"
                      :value="pos"
                    >
                      {{ pos }}
                    </option>
                  </select>
                  <div v-else class="text-gray-600 text-xs text-center">
                    -
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- Pitcher slot (10) -->
          <div class="mb-6 select-none">
            <div class="flex items-center gap-2 mb-3">
              <h3 class="text-sm font-semibold text-gray-300">Starting Pitcher</h3>
              <span v-if="pitcherSlotDisabled" class="text-xs text-yellow-500 bg-yellow-500/10 px-2 py-0.5 rounded-full">
                Pitcher in batting order
              </span>
            </div>
            <div
              :class="[
                'bg-gray-800/60 backdrop-blur-sm rounded-lg border transition-all duration-200',
                pitcherSlotDisabled ? 'opacity-40 pointer-events-none border-gray-700/20' : 'border-gray-700/50',
                isReplacementMode(9) ? 'ring-2 ring-amber-500/50 border-amber-500/50' : ''
              ]"
            >
              <div class="flex items-center gap-3 p-2.5">
                <div :class="[
                  'flex-shrink-0 w-8 h-8 rounded-lg flex items-center justify-center transition-colors',
                  isReplacementMode(9) ? 'bg-amber-900/50' : 'bg-green-900/30'
                ]">
                  <span :class="[
                    'text-sm font-bold',
                    isReplacementMode(9) ? 'text-amber-400' : 'text-green-400'
                  ]">P</span>
                </div>

                <!-- Pitcher slot - vuedraggable drop zone -->
                <draggable
                  :list="getSlotPlayers(9)"
                  :group="{ name: 'lineup', pull: true, put: !pitcherSlotDisabled }"
                  item-key="id"
                  v-bind="dragOptions"
                  :class="[
                    'flex-1 min-w-0 min-h-[44px] slot-drop-zone',
                    isReplacementMode(9) ? 'replacement-mode' : ''
                  ]"
                  @change="(e: any) => handleSlotChange(9, e)"
                  @start="handleDragStart"
                  @end="handleDragEnd"
                  :move="(evt: any) => handleSlotMove(evt, 9)"
                >
                  <template #item="{ element: player }">
                    <div
                      :class="[
                        'rounded-lg p-2 cursor-grab active:cursor-grabbing transition-all duration-150 flex items-center gap-2.5 group border select-none touch-manipulation',
                        isReplacementMode(9)
                          ? 'bg-amber-900/40 border-amber-600/50 opacity-60'
                          : 'bg-green-900/40 hover:bg-green-900/60 border-green-700/30'
                      ]"
                    >
                      <!-- Player Headshot -->
                      <div class="flex-shrink-0">
                        <img
                          v-if="getPlayerPreviewImage(player)"
                          :src="getPlayerPreviewImage(player)!"
                          :alt="player.name"
                          class="w-9 h-9 rounded-full object-cover bg-gray-600 ring-2 ring-green-600/30"
                          @error="(e) => (e.target as HTMLImageElement).style.display = 'none'"
                        />
                        <div v-else class="w-9 h-9 rounded-full bg-gradient-to-br from-green-700 to-green-800 flex items-center justify-center text-green-200 text-sm font-bold ring-2 ring-green-600/30">
                          {{ getPlayerFallbackInitial(player) }}
                        </div>
                      </div>

                      <!-- Player Info -->
                      <div class="flex-1 min-w-0">
                        <div class="font-medium text-white truncate text-sm">{{ player.name }}</div>
                        <div class="text-[10px] text-green-400/80 mt-0.5">Pitcher</div>
                      </div>

                      <!-- Info Button -->
                      <button
                        class="flex-shrink-0 w-6 h-6 rounded-full bg-green-800/50 hover:bg-green-600 text-green-300 hover:text-white text-xs flex items-center justify-center opacity-0 group-hover:opacity-100 transition-all"
                        @click.stop="openPlayerPreview(player)"
                      >
                        <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
                        </svg>
                      </button>

                      <!-- Remove Button -->
                      <button
                        class="flex-shrink-0 w-6 h-6 rounded-full bg-red-900/30 hover:bg-red-900/60 text-red-400 hover:text-red-300 text-xs flex items-center justify-center transition-all"
                        @click.stop="removePlayer(9)"
                      >
                        <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
                        </svg>
                      </button>
                    </div>
                  </template>
                  <template #footer>
                    <!-- Replacement indicator when dragging over occupied pitcher slot -->
                    <div
                      v-if="isReplacementMode(9)"
                      class="absolute inset-0 flex items-center justify-center bg-amber-900/20 rounded-lg pointer-events-none z-10"
                    >
                      <span class="text-xs font-medium text-amber-400 bg-amber-950/80 px-2 py-1 rounded">
                        Replacing {{ getReplacedPlayer(9)?.name }}
                      </span>
                    </div>
                    <!-- Empty slot placeholder -->
                    <div v-else-if="!pitcherPlayer" class="border-2 border-dashed border-gray-600/50 rounded-lg py-3 px-4 text-center text-gray-500 text-xs transition-colors hover:border-gray-500/50 hover:bg-gray-800/30">
                      Drop pitcher here
                    </div>
                  </template>
                </draggable>

                <div class="w-20 flex-shrink-0">
                  <div :class="[
                    'text-xs text-center font-medium',
                    isReplacementMode(9) ? 'text-amber-400' : 'text-green-500'
                  ]">P</div>
                </div>
              </div>
            </div>
          </div>

          <!-- Validation errors -->
          <div v-if="validationErrors.length > 0" class="bg-red-950/50 border border-red-800/50 rounded-xl p-4 mb-4">
            <div class="flex items-start gap-3">
              <div class="flex-shrink-0 w-8 h-8 rounded-full bg-red-900/50 flex items-center justify-center">
                <svg class="w-4 h-4 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
                </svg>
              </div>
              <div>
                <div class="font-semibold text-red-300 text-sm mb-1">Please fix the following:</div>
                <ul class="space-y-1">
                  <li v-for="error in validationErrors" :key="error" class="text-xs text-red-400/90 flex items-center gap-1.5">
                    <span class="w-1 h-1 rounded-full bg-red-400/60" />
                    {{ error }}
                  </li>
                </ul>
              </div>
            </div>
          </div>

          <!-- Submit button (per-team) -->
          <div class="sticky bottom-4 pt-4 space-y-3">
            <!-- Already submitted status -->
            <div
              v-if="isActiveTeamSubmitted"
              class="bg-green-950/50 border border-green-800/50 rounded-xl p-4 text-center"
            >
              <div class="flex items-center justify-center gap-2 text-green-400">
                <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
                </svg>
                <span class="font-semibold">{{ activeTab === 'home' ? 'Home' : 'Away' }} Lineup Submitted</span>
              </div>
              <p class="text-sm text-gray-400 mt-1">
                {{ (activeTab === 'home' ? awaySubmitted : homeSubmitted) ? 'Both teams ready!' : 'Waiting for other team...' }}
              </p>
            </div>

            <!-- Submit button -->
            <ActionButton
              v-else
              variant="success"
              size="lg"
              full-width
              :disabled="!canSubmitActiveTeam"
              :loading="isSubmittingActiveTeam"
              @click="submitActiveTeamLineup"
            >
              {{ isSubmittingActiveTeam
                ? 'Submitting...'
                : (canSubmitActiveTeam
                    ? `Submit ${activeTab === 'home' ? 'Home' : 'Away'} Lineup`
                    : 'Complete Lineup to Submit')
              }}
            </ActionButton>

            <!-- Status indicators for both teams -->
            <div class="flex justify-center gap-4 text-xs">
              <div :class="homeSubmitted ? 'text-green-400' : 'text-gray-500'">
                <span class="inline-block w-2 h-2 rounded-full mr-1" :class="homeSubmitted ? 'bg-green-400' : 'bg-gray-600'" />
                Home: {{ homeSubmitted ? 'Submitted' : 'Pending' }}
              </div>
              <div :class="awaySubmitted ? 'text-green-400' : 'text-gray-500'">
                <span class="inline-block w-2 h-2 rounded-full mr-1" :class="awaySubmitted ? 'bg-green-400' : 'bg-gray-600'" />
                Away: {{ awaySubmitted ? 'Submitted' : 'Pending' }}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- Player Preview Modal -->
    <Teleport to="body">
      <div
        v-if="showPreview && previewPlayer"
        class="fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4"
        @click.self="closePlayerPreview"
      >
        <div class="bg-gray-800 rounded-xl max-w-md w-full max-h-[90vh] overflow-y-auto shadow-2xl">
          <!-- Modal Header -->
          <div class="relative">
            <!-- Large Player Image -->
            <div class="h-48 bg-gradient-to-b from-blue-900 to-gray-800 flex items-center justify-center">
              <img
                v-if="getPlayerPreviewImage(previewPlayer)"
                :src="getPlayerPreviewImage(previewPlayer)!"
                :alt="previewPlayer.name"
                class="w-32 h-32 rounded-full object-cover border-4 border-gray-700 shadow-lg"
                @error="(e) => (e.target as HTMLImageElement).style.display = 'none'"
              />
              <div v-else class="w-32 h-32 rounded-full bg-gray-700 flex items-center justify-center text-gray-400 text-3xl font-bold border-4 border-gray-600">
                {{ getPlayerFallbackInitial(previewPlayer) }}
              </div>
            </div>

            <!-- Close Button -->
            <button
              class="absolute top-3 right-3 w-8 h-8 rounded-full bg-gray-900/80 hover:bg-gray-700 text-gray-400 hover:text-white flex items-center justify-center transition-colors"
              @click="closePlayerPreview"
            >
              x
            </button>
          </div>

          <!-- Player Info -->
          <div class="p-6">
            <h2 class="text-2xl font-bold text-center mb-1">{{ previewPlayer.name }}</h2>
            <p class="text-gray-400 text-center text-sm mb-4">
              {{ getPlayerPositions(previewPlayer).filter(p => p !== 'DH').join(' / ') || 'Designated Hitter' }}
            </p>

            <!-- Stats Grid -->
            <div class="grid grid-cols-2 gap-4 mb-4">
              <!-- Positions -->
              <div class="bg-gray-700/50 rounded-lg p-3">
                <div class="text-xs text-gray-400 uppercase tracking-wide mb-1">Positions</div>
                <div class="flex flex-wrap gap-1">
                  <span
                    v-for="pos in getPlayerPositions(previewPlayer).filter(p => p !== 'DH')"
                    :key="pos"
                    class="px-2 py-0.5 bg-blue-900 text-blue-200 text-xs rounded"
                  >
                    {{ pos }}
                  </span>
                  <span v-if="getPlayerPositions(previewPlayer).filter(p => p !== 'DH').length === 0" class="text-gray-500 text-sm">
                    DH Only
                  </span>
                </div>
              </div>

              <!-- WAR -->
              <div class="bg-gray-700/50 rounded-lg p-3">
                <div class="text-xs text-gray-400 uppercase tracking-wide mb-1">WAR</div>
                <div class="text-xl font-bold">
                  {{ previewPlayer.wara?.toFixed(1) || '-' }}
                </div>
              </div>
            </div>

            <!-- Close Button -->
            <button
              class="w-full py-2 bg-gray-700 hover:bg-gray-600 rounded-lg text-gray-300 hover:text-white transition-colors"
              @click="closePlayerPreview"
            >
              Close
            </button>
          </div>
        </div>
      </div>
    </Teleport>
  </div>
</template>

<style scoped>
/* Prevent text selection on all draggable elements AND their children - critical for mobile UX */
:deep([draggable="true"]),
:deep([draggable="true"] *),
:deep(.sortable-item),
:deep(.sortable-item *),
.roster-item,
.roster-item *,
.lineup-slot-item,
.lineup-slot-item * {
  -webkit-user-select: none !important;
  -moz-user-select: none !important;
  -ms-user-select: none !important;
  user-select: none !important;
  -webkit-touch-callout: none !important; /* Prevent iOS callout menu */
}

/* Touch action on containers only (not children) */
:deep([draggable="true"]),
:deep(.sortable-item) {
  touch-action: manipulation; /* Allow pan/zoom but optimize for touch */
}

/* Apply to the draggable container itself */
:deep(.sortable-chosen),
:deep(.sortable-chosen *) {
  -webkit-user-select: none !important;
  user-select: none !important;
}

/* Slot drop zone - constrain to single item height */
.slot-drop-zone {
  position: relative;
  max-height: 60px; /* Constrain to single player card height */
  overflow: hidden; /* Hide stacking preview */
}

/* Replacement mode - show that an item will be replaced */
.slot-drop-zone.replacement-mode {
  max-height: none; /* Allow replacement indicator to show */
}

/* Hide the ghost/preview when in replacement mode to prevent stacking visual */
.slot-drop-zone.replacement-mode :deep(.sortable-ghost) {
  display: none !important;
}

/* Vuedraggable drag effect styles */
.drag-ghost {
  @apply opacity-50 bg-blue-900/30 border-2 border-dashed border-blue-500;
}

.drag-chosen {
  @apply ring-2 ring-blue-500 ring-offset-2 ring-offset-gray-900;
}

.drag-dragging {
  @apply opacity-75 scale-105 shadow-xl shadow-blue-500/20;
}

/* Ensure draggable containers have proper touch handling */
:deep(.sortable-drag) {
  opacity: 0.8;
  transform: scale(1.02);
}

:deep(.sortable-ghost) {
  opacity: 0.4;
}

/* In replacement mode, style the ghost differently */
.slot-drop-zone.replacement-mode :deep(.sortable-fallback) {
  opacity: 0 !important;
}
</style>
