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

// Helper to create mock player
function createMockPlayer(id: number, name: string, positions: string[]): SbaPlayer {
  const player: SbaPlayer = {
    id,
    name,
    image: `player-${id}.jpg`,
    pos_1: null,
    pos_2: null,
    pos_3: null,
    pos_4: null,
    pos_5: null,
    pos_6: null,
    pos_7: null,
    pos_8: null,
    wara: 1.5,
    team_id: 1,
    team_name: 'Test Team',
    season: '2024',
    strat_code: null,
    bbref_id: null,
    injury_rating: null,
  }

  positions.forEach((pos, index) => {
    const key = `pos_${index + 1}` as keyof SbaPlayer
    ;(player as any)[key] = pos
  })

  return player
}

// Helper to create mock lineup entry
function createMockLineup(
  id: number,
  player: SbaPlayer,
  isActive: boolean,
  position = 'P',
  isFatigued = false,
  enteredInning = 1
): 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,
    batting_order: null,
    is_starter: true,
    is_active: isActive,
    entered_inning: enteredInning,
    replacing_id: null,
    after_play: null,
    is_fatigued: isFatigued,
    player,
  }
}

describe('PitchingChangeSelector', () => {
  const mockCurrentPitcher = createMockLineup(
    1,
    createMockPlayer(101, 'John Starter', ['P']),
    true,
    'P',
    false,
    1
  )

  const mockBenchPlayers = [
    createMockLineup(2, createMockPlayer(201, 'Relief Pitcher 1', ['P']), false),
    createMockLineup(3, createMockPlayer(202, 'Relief Pitcher 2', ['P']), false),
    createMockLineup(4, createMockPlayer(203, 'Position Player', ['1B', 'OF']), false),
  ]

  const defaultProps = {
    currentPitcher: mockCurrentPitcher,
    benchPlayers: mockBenchPlayers,
    teamId: 1,
  }

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

      expect(wrapper.text()).toContain('Pitching Change')
    })

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

      expect(wrapper.text()).toContain('Current Pitcher:')
      expect(wrapper.text()).toContain('John Starter')
      expect(wrapper.text()).toContain('Entered Inning 1')
    })

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

      expect(wrapper.text()).toContain('Bring in a relief pitcher to replace John Starter')
    })

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

      expect(wrapper.text()).toContain('Cancel')
      expect(wrapper.text()).toContain('Bring in Reliever')
    })
  })

  describe('Pitcher Filtering', () => {
    it('filters to only show pitchers from bench', () => {
      const wrapper = mount(PitchingChangeSelector, {
        props: defaultProps,
      })

      expect(wrapper.text()).toContain('Relief Pitcher 1')
      expect(wrapper.text()).toContain('Relief Pitcher 2')
      expect(wrapper.text()).not.toContain('Position Player')
    })

    it('filters out active pitchers', () => {
      const mixedBench = [
        createMockLineup(2, createMockPlayer(201, 'Active Pitcher', ['P']), true),
        createMockLineup(3, createMockPlayer(202, 'Bench Pitcher', ['P']), false),
      ]

      const wrapper = mount(PitchingChangeSelector, {
        props: {
          ...defaultProps,
          benchPlayers: mixedBench,
        },
      })

      expect(wrapper.text()).not.toContain('Active Pitcher')
      expect(wrapper.text()).toContain('Bench Pitcher')
    })

    it('shows fatigued pitchers but marks them as unavailable', () => {
      const mixedBench = [
        createMockLineup(2, createMockPlayer(201, 'Fatigued Pitcher', ['P']), false, 'P', true),
        createMockLineup(3, createMockPlayer(202, 'Fresh Pitcher', ['P']), false),
      ]

      const wrapper = mount(PitchingChangeSelector, {
        props: {
          ...defaultProps,
          benchPlayers: mixedBench,
        },
      })

      expect(wrapper.text()).toContain('Fatigued Pitcher')
      expect(wrapper.text()).toContain('Fatigued')
      expect(wrapper.text()).toContain('Fresh Pitcher')
    })

    it('shows no pitchers message when no eligible relievers', () => {
      const wrapper = mount(PitchingChangeSelector, {
        props: {
          ...defaultProps,
          benchPlayers: [
            createMockLineup(2, createMockPlayer(201, 'Only Fielder', ['1B']), false),
          ],
        },
      })

      expect(wrapper.text()).toContain('No relief pitchers available')
    })
  })

  describe('Pitcher Selection', () => {
    it('allows selecting a relief pitcher', async () => {
      const wrapper = mount(PitchingChangeSelector, {
        props: defaultProps,
      })

      const pitcherCards = wrapper.findAll('.reliever-card')
      await pitcherCards[0].trigger('click')

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

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

      const pitcherCards = wrapper.findAll('.reliever-card')
      await pitcherCards[0].trigger('click')
      await wrapper.vm.$nextTick()

      expect(pitcherCards[0].classes()).toContain('reliever-selected')
    })

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

      const pitcherCards = wrapper.findAll('.reliever-card')
      await pitcherCards[0].trigger('click')
      await wrapper.vm.$nextTick()

      expect(pitcherCards[0].find('.selected-indicator').exists()).toBe(true)
    })

    it('prevents selecting fatigued pitcher', async () => {
      const mixedBench = [
        createMockLineup(2, createMockPlayer(201, 'Fatigued Pitcher', ['P']), false, 'P', true),
      ]

      const wrapper = mount(PitchingChangeSelector, {
        props: {
          ...defaultProps,
          benchPlayers: mixedBench,
        },
      })

      const pitcherCards = wrapper.findAll('.reliever-card')
      await pitcherCards[0].trigger('click')

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

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

      const pitcherCards = wrapper.findAll('.reliever-card')
      await pitcherCards[0].trigger('click')
      expect(wrapper.vm.selectedPitcherId).toBe(201)

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

  describe('Fatigue Display', () => {
    it('shows fatigue indicator for current pitcher when fatigued', () => {
      const fatiguedPitcher = createMockLineup(
        1,
        createMockPlayer(101, 'Tired Starter', ['P']),
        true,
        'P',
        true
      )

      const wrapper = mount(PitchingChangeSelector, {
        props: {
          ...defaultProps,
          currentPitcher: fatiguedPitcher,
        },
      })

      expect(wrapper.text()).toContain('Fatigued')
    })

    it('shows fatigue badge on relief pitchers who are fatigued', () => {
      const mixedBench = [
        createMockLineup(2, createMockPlayer(201, 'Fatigued Reliever', ['P']), false, 'P', true),
      ]

      const wrapper = mount(PitchingChangeSelector, {
        props: {
          ...defaultProps,
          benchPlayers: mixedBench,
        },
      })

      const fatigueBadges = wrapper.findAll('.fatigue-badge')
      expect(fatigueBadges.length).toBeGreaterThan(0)
    })
  })

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

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

    it('enables submit when fresh pitcher selected', async () => {
      const wrapper = mount(PitchingChangeSelector, {
        props: defaultProps,
      })

      const pitcherCards = wrapper.findAll('.reliever-card')
      await pitcherCards[0].trigger('click')
      await wrapper.vm.$nextTick()

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

    it('disables submit when fatigued pitcher selected', async () => {
      const mixedBench = [
        createMockLineup(2, createMockPlayer(201, 'Fatigued Pitcher', ['P']), false, 'P', true),
      ]

      const wrapper = mount(PitchingChangeSelector, {
        props: {
          ...defaultProps,
          benchPlayers: mixedBench,
        },
      })

      // Try to select fatigued pitcher (should be prevented)
      const pitcherCards = wrapper.findAll('.reliever-card')
      await pitcherCards[0].trigger('click')

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

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

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

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

      const pitcherCards = wrapper.findAll('.reliever-card')
      await pitcherCards[0].trigger('click')

      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(PitchingChangeSelector, {
        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(PitchingChangeSelector, {
        props: defaultProps,
      })

      const pitcherCards = wrapper.findAll('.reliever-card')
      await pitcherCards[0].trigger('click')
      expect(wrapper.vm.selectedPitcherId).toBe(201)

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

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

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

      const pitcherCards = wrapper.findAll('.reliever-card')
      await pitcherCards[0].trigger('click')
      expect(wrapper.vm.selectedPitcherId).toBe(201)

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

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

  describe('Pitcher Metadata Display', () => {
    it('displays pitcher role', () => {
      const wrapper = mount(PitchingChangeSelector, {
        props: defaultProps,
      })

      expect(wrapper.text()).toContain('Pitcher')
    })

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

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

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

      expect(wrapper.text()).toContain('Bring in a relief pitcher to replace current pitcher')
    })

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

      const pitcherCards = wrapper.findAll('.reliever-card')
      if (pitcherCards.length > 0) {
        await pitcherCards[0].trigger('click')
      }

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

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

    it('disables fatigued pitcher card with styling', () => {
      const mixedBench = [
        createMockLineup(2, createMockPlayer(201, 'Fatigued Pitcher', ['P']), false, 'P', true),
      ]

      const wrapper = mount(PitchingChangeSelector, {
        props: {
          ...defaultProps,
          benchPlayers: mixedBench,
        },
      })

      const pitcherCards = wrapper.findAll('.reliever-card')
      expect(pitcherCards[0].classes()).toContain('reliever-fatigued')
      expect(pitcherCards[0].attributes('disabled')).toBeDefined()
    })
  })
})
