import { describe, it, expect, beforeEach } from 'vitest'
import { mount } from '@vue/test-utils'
import PinchHitterSelector from '~/components/Substitutions/PinchHitterSelector.vue'
import type { Lineup, SbaPlayer } from '~/types'

// Helper to create mock player
function createMockPlayer(id: number, name: string, pos1?: string): SbaPlayer {
  return {
    id,
    name,
    image: `player-${id}.jpg`,
    pos_1: pos1 || 'OF',
    pos_2: null,
    pos_3: null,
    pos_4: null,
    pos_5: null,
    pos_6: null,
    pos_7: null,
    pos_8: null,
    wara: 2.5,
    team_id: 1,
    team_name: 'Test Team',
    season: '2024',
    strat_code: null,
    bbref_id: null,
    injury_rating: null,
  }
}

// Helper to create mock lineup entry
function createMockLineup(id: number, player: SbaPlayer, isActive: boolean, isFatigued = false): Lineup {
  return {
    lineup_id: id,          // Changed from 'id' to 'lineup_id'
    card_id: player.id,      // Changed from 'player_id' to 'card_id'
    game_id: 'test-game-123',
    team_id: 1,
    position: 'OF',
    batting_order: isActive ? 1 : null,
    is_starter: false,
    is_active: isActive,
    entered_inning: 1,
    replacing_id: null,
    after_play: null,
    is_fatigued: isFatigued,
    player,
  }
}

describe('PinchHitterSelector', () => {
  const mockBatter = createMockLineup(
    1,
    createMockPlayer(101, 'John Batter'),
    true
  )

  const mockBenchPlayers = [
    createMockLineup(2, createMockPlayer(201, 'Bench Player 1'), false),
    createMockLineup(3, createMockPlayer(202, 'Bench Player 2'), false),
    createMockLineup(4, createMockPlayer(203, 'Bench Player 3'), false),
  ]

  const defaultProps = {
    playerOut: mockBatter,
    benchPlayers: mockBenchPlayers,
    teamId: 1,
  }

  describe('Rendering', () => {
    it('renders component with header', () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      expect(wrapper.text()).toContain('Pinch Hitter')
    })

    it('displays current batter information', () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      expect(wrapper.text()).toContain('Current Batter:')
      expect(wrapper.text()).toContain('John Batter')
    })

    it('shows descriptive text with batter name', () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      expect(wrapper.text()).toContain('Select a player from the bench to bat in place of John Batter')
    })

    it('renders available bench players', () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      expect(wrapper.text()).toContain('Bench Player 1')
      expect(wrapper.text()).toContain('Bench Player 2')
      expect(wrapper.text()).toContain('Bench Player 3')
    })

    it('renders action buttons', () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      expect(wrapper.text()).toContain('Cancel')
      expect(wrapper.text()).toContain('Substitute Player')
    })
  })

  describe('Player Filtering', () => {
    it('filters out active players from bench list', () => {
      const mixedPlayers = [
        createMockLineup(2, createMockPlayer(201, 'Active Player'), true),
        createMockLineup(3, createMockPlayer(202, 'Bench Player 1'), false),
        createMockLineup(4, createMockPlayer(203, 'Bench Player 2'), false),
      ]

      const wrapper = mount(PinchHitterSelector, {
        props: {
          ...defaultProps,
          benchPlayers: mixedPlayers,
        },
      })

      expect(wrapper.text()).not.toContain('Active Player')
      expect(wrapper.text()).toContain('Bench Player 1')
      expect(wrapper.text()).toContain('Bench Player 2')
    })

    it('filters out fatigued players from bench list', () => {
      const mixedPlayers = [
        createMockLineup(2, createMockPlayer(201, 'Fatigued Player'), false, true),
        createMockLineup(3, createMockPlayer(202, 'Available Player'), false),
      ]

      const wrapper = mount(PinchHitterSelector, {
        props: {
          ...defaultProps,
          benchPlayers: mixedPlayers,
        },
      })

      expect(wrapper.text()).not.toContain('Fatigued Player')
      expect(wrapper.text()).toContain('Available Player')
    })

    it('shows no players message when no eligible bench players', () => {
      const wrapper = mount(PinchHitterSelector, {
        props: {
          ...defaultProps,
          benchPlayers: [],
        },
      })

      expect(wrapper.text()).toContain('No eligible bench players available')
    })
  })

  describe('Player Selection', () => {
    it('allows selecting a bench player', async () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      const playerCards = wrapper.findAll('.bench-player-card')
      await playerCards[0].trigger('click')

      expect(wrapper.vm.selectedPlayerId).toBe(201)
    })

    it('highlights selected player', async () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      const playerCards = wrapper.findAll('.bench-player-card')
      await playerCards[0].trigger('click')

      expect(playerCards[0].classes()).toContain('bench-player-selected')
    })

    it('shows checkmark icon on selected player', async () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      const playerCards = wrapper.findAll('.bench-player-card')
      await playerCards[0].trigger('click')
      await wrapper.vm.$nextTick()

      const selectedCard = playerCards[0]
      expect(selectedCard.find('.selected-indicator').exists()).toBe(true)
    })

    it('allows changing selection to different player', async () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      const playerCards = wrapper.findAll('.bench-player-card')
      await playerCards[0].trigger('click')
      expect(wrapper.vm.selectedPlayerId).toBe(201)

      await playerCards[1].trigger('click')
      expect(wrapper.vm.selectedPlayerId).toBe(202)
    })
  })

  describe('Submit Validation', () => {
    it('disables submit button when no player selected', () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      const submitButton = wrapper.findAll('button').find(btn => btn.text().includes('Substitute Player'))
      expect(submitButton?.attributes('disabled')).toBeDefined()
    })

    it('enables submit button when player selected', async () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      const playerCards = wrapper.findAll('.bench-player-card')
      await playerCards[0].trigger('click')
      await wrapper.vm.$nextTick()

      const submitButton = wrapper.findAll('button').find(btn => btn.text().includes('Substitute Player'))
      expect(submitButton?.attributes('disabled')).toBeUndefined()
    })

    it('disables submit button when playerOut is null', () => {
      const wrapper = mount(PinchHitterSelector, {
        props: {
          ...defaultProps,
          playerOut: null,
        },
      })

      const submitButton = wrapper.findAll('button').find(btn => btn.text().includes('Substitute Player'))
      expect(submitButton?.attributes('disabled')).toBeDefined()
    })
  })

  describe('Emit Events', () => {
    it('emits submit event with correct payload', async () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      // Select a player
      const playerCards = wrapper.findAll('.bench-player-card')
      await playerCards[0].trigger('click')

      // Click submit
      const submitButton = wrapper.find('.button-submit')
      await submitButton.trigger('click')

      expect(wrapper.emitted()).toHaveProperty('submit')
      const submitEvents = wrapper.emitted('submit')
      expect(submitEvents).toHaveLength(1)
      expect(submitEvents![0]).toEqual([{
        playerOutLineupId: 1,
        playerInCardId: 201,
        teamId: 1,
      }])
    })

    it('emits cancel event when cancel clicked', async () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      const cancelButton = wrapper.find('.button-cancel')
      await cancelButton.trigger('click')

      expect(wrapper.emitted()).toHaveProperty('cancel')
      expect(wrapper.emitted('cancel')).toHaveLength(1)
    })

    it('resets selection after submit', async () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      const playerCards = wrapper.findAll('.bench-player-card')
      await playerCards[0].trigger('click')
      expect(wrapper.vm.selectedPlayerId).toBe(201)

      const submitButton = wrapper.find('.button-submit')
      await submitButton.trigger('click')

      expect(wrapper.vm.selectedPlayerId).toBeNull()
    })

    it('resets selection after cancel', async () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      const playerCards = wrapper.findAll('.bench-player-card')
      await playerCards[0].trigger('click')
      expect(wrapper.vm.selectedPlayerId).toBe(201)

      const cancelButton = wrapper.find('.button-cancel')
      await cancelButton.trigger('click')

      expect(wrapper.vm.selectedPlayerId).toBeNull()
    })
  })

  describe('Player Metadata Display', () => {
    it('displays player positions', () => {
      const playerWithMultiPos = createMockPlayer(301, 'Multi Position')
      playerWithMultiPos.pos_1 = '1B'
      playerWithMultiPos.pos_2 = 'OF'
      playerWithMultiPos.pos_3 = '3B'

      const bench = [createMockLineup(5, playerWithMultiPos, false)]

      const wrapper = mount(PinchHitterSelector, {
        props: {
          ...defaultProps,
          benchPlayers: bench,
        },
      })

      expect(wrapper.text()).toContain('1B, OF, 3B')
    })

    it('displays WARA stat when available', () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      expect(wrapper.text()).toContain('WARA: 2.5')
    })

    it('limits position display to first 3 positions', () => {
      const playerWithManyPos = createMockPlayer(401, 'Utility')
      playerWithManyPos.pos_1 = '1B'
      playerWithManyPos.pos_2 = '2B'
      playerWithManyPos.pos_3 = '3B'
      playerWithManyPos.pos_4 = 'SS'

      const bench = [createMockLineup(6, playerWithManyPos, false)]

      const wrapper = mount(PinchHitterSelector, {
        props: {
          ...defaultProps,
          benchPlayers: bench,
        },
      })

      const text = wrapper.text()
      expect(text).toContain('1B, 2B, 3B')
      expect(text).not.toContain('SS')
    })
  })

  describe('Edge Cases', () => {
    it('handles missing playerOut gracefully', () => {
      const wrapper = mount(PinchHitterSelector, {
        props: {
          ...defaultProps,
          playerOut: null,
        },
      })

      expect(wrapper.text()).toContain('Select a player from the bench to bat in place of current batter')
    })

    it('prevents submit when playerOut is null', async () => {
      const wrapper = mount(PinchHitterSelector, {
        props: {
          ...defaultProps,
          playerOut: null,
        },
      })

      const playerCards = wrapper.findAll('.bench-player-card')
      await playerCards[0].trigger('click')

      const submitButton = wrapper.findAll('button').find(btn => btn.text().includes('Substitute Player'))
      if (submitButton) {
        await submitButton.trigger('click')
      }

      expect(wrapper.emitted('submit')).toBeUndefined()
    })

    it('prevents submit when no player selected even after clicking submit', async () => {
      const wrapper = mount(PinchHitterSelector, {
        props: defaultProps,
      })

      const submitButton = wrapper.findAll('button').find(btn => btn.text().includes('Substitute Player'))
      if (submitButton) {
        await submitButton.trigger('click')
      }

      expect(wrapper.emitted('submit')).toBeUndefined()
    })
  })
})
