import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import SubstitutionPanel from '~/components/Substitutions/SubstitutionPanel.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: 2.0,
    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 = 'OF',
  battingOrder: number | null = null
): Lineup {
  return {
    id,
    game_id: 'test-game-123',
    team_id: 1,
    player_id: player.id,
    position,
    batting_order: battingOrder,
    is_starter: true,
    is_active: isActive,
    entered_inning: 1,
    replacing_id: null,
    after_play: null,
    is_fatigued: false,
    player,
  }
}

describe('SubstitutionPanel', () => {
  const mockCurrentLineup = [
    createMockLineup(1, createMockPlayer(101, 'John Pitcher', ['P']), true, 'P', null),
    createMockLineup(2, createMockPlayer(102, 'Jane Catcher', ['C']), true, 'C', 1),
    createMockLineup(3, createMockPlayer(103, 'Bob First', ['1B']), true, '1B', 2),
    createMockLineup(4, createMockPlayer(104, 'Sally Second', ['2B']), true, '2B', 3),
  ]

  const mockBenchPlayers = [
    createMockLineup(5, createMockPlayer(201, 'Relief Pitcher', ['P']), false),
    createMockLineup(6, createMockPlayer(202, 'Bench Hitter', ['OF']), false),
    createMockLineup(7, createMockPlayer(203, 'Utility Player', ['2B', '3B', 'SS']), false),
  ]

  const defaultProps = {
    gameId: 'test-game-123',
    teamId: 1,
    currentLineup: mockCurrentLineup,
    benchPlayers: mockBenchPlayers,
    currentPitcher: mockCurrentLineup[0],
    currentBatter: mockCurrentLineup[1],
  }

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

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

    it('renders all three tab buttons', () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      expect(wrapper.text()).toContain('Pinch Hitter')
      expect(wrapper.text()).toContain('Defensive Sub')
      expect(wrapper.text()).toContain('Pitching Change')
    })

    it('shows idle state by default', () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      expect(wrapper.text()).toContain('Select a substitution type above')
    })

    it('displays status indicator', () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const statusIndicator = wrapper.find('.status-indicator')
      expect(statusIndicator.exists()).toBe(true)
    })
  })

  describe('Tab Navigation', () => {
    it('activates pinch hitter tab when clicked', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const pinchHitterTab = tabs.find(tab => tab.text().includes('Pinch Hitter'))
      await pinchHitterTab!.trigger('click')

      expect(wrapper.vm.currentTab).toBe('pinch_hitter')
    })

    it('activates defensive replacement tab when clicked', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const defensiveTab = tabs.find(tab => tab.text().includes('Defensive Sub'))
      await defensiveTab!.trigger('click')

      expect(wrapper.vm.currentTab).toBe('defensive_replacement')
    })

    it('activates pitching change tab when clicked', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const pitchingTab = tabs.find(tab => tab.text().includes('Pitching Change'))
      await pitchingTab!.trigger('click')

      expect(wrapper.vm.currentTab).toBe('pitching_change')
    })

    it('highlights active tab', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const pinchHitterTab = tabs.find(tab => tab.text().includes('Pinch Hitter'))
      await pinchHitterTab!.trigger('click')
      await wrapper.vm.$nextTick()

      expect(pinchHitterTab!.classes()).toContain('tab-active')
    })

    it('allows switching between tabs', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const pinchHitterTab = tabs.find(tab => tab.text().includes('Pinch Hitter'))
      const pitchingTab = tabs.find(tab => tab.text().includes('Pitching Change'))

      await pinchHitterTab!.trigger('click')
      expect(wrapper.vm.currentTab).toBe('pinch_hitter')

      await pitchingTab!.trigger('click')
      expect(wrapper.vm.currentTab).toBe('pitching_change')
    })
  })

  describe('Pinch Hitter Mode', () => {
    it('renders PinchHitterSelector when tab selected', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const pinchHitterTab = tabs.find(tab => tab.text().includes('Pinch Hitter'))
      await pinchHitterTab!.trigger('click')
      await wrapper.vm.$nextTick()

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

    it('shows instruction box for pinch hitter', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const pinchHitterTab = tabs.find(tab => tab.text().includes('Pinch Hitter'))
      await pinchHitterTab!.trigger('click')
      await wrapper.vm.$nextTick()

      const instructionBox = wrapper.find('.instruction-box')
      expect(instructionBox.exists()).toBe(true)
    })
  })

  describe('Defensive Replacement Mode', () => {
    it('renders DefensiveReplacementSelector when tab selected', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const defensiveTab = tabs.find(tab => tab.text().includes('Defensive Sub'))
      await defensiveTab!.trigger('click')
      await wrapper.vm.$nextTick()

      expect(wrapper.text()).toContain('Replace a defensive player with a bench player')
    })

    it('shows active fielders for selection', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const defensiveTab = tabs.find(tab => tab.text().includes('Defensive Sub'))
      await defensiveTab!.trigger('click')
      await wrapper.vm.$nextTick()

      expect(wrapper.text()).toContain('Select player to replace:')
      expect(wrapper.text()).toContain('Jane Catcher')
      expect(wrapper.text()).toContain('Bob First')
    })

    it('excludes pitcher from defensive replacement selection', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const defensiveTab = tabs.find(tab => tab.text().includes('Defensive Sub'))
      await defensiveTab!.trigger('click')
      await wrapper.vm.$nextTick()

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

  describe('Pitching Change Mode', () => {
    it('renders PitchingChangeSelector when tab selected', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const pitchingTab = tabs.find(tab => tab.text().includes('Pitching Change'))
      await pitchingTab!.trigger('click')
      await wrapper.vm.$nextTick()

      expect(wrapper.text()).toContain('Bring in a relief pitcher from the bench')
    })
  })

  describe('Event Emissions', () => {
    it('emits pinchHitter event with correct payload', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const pinchHitterTab = tabs.find(tab => tab.text().includes('Pinch Hitter'))
      await pinchHitterTab!.trigger('click')

      const testPayload = {
        playerOutLineupId: 1,
        playerInCardId: 201,
        teamId: 1,
      }

      // Manually trigger the handler
      wrapper.vm.handlePinchHitterSubmit(testPayload)
      await wrapper.vm.$nextTick()

      expect(wrapper.emitted()).toHaveProperty('pinchHitter')
      expect(wrapper.emitted('pinchHitter')![0]).toEqual([testPayload])
    })

    it('emits defensiveReplacement event with correct payload', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const testPayload = {
        playerOutLineupId: 2,
        playerInCardId: 203,
        newPosition: '2B',
        teamId: 1,
      }

      wrapper.vm.handleDefensiveReplacementSubmit(testPayload)
      await wrapper.vm.$nextTick()

      expect(wrapper.emitted()).toHaveProperty('defensiveReplacement')
      expect(wrapper.emitted('defensiveReplacement')![0]).toEqual([testPayload])
    })

    it('emits pitchingChange event with correct payload', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const testPayload = {
        playerOutLineupId: 1,
        playerInCardId: 201,
        teamId: 1,
      }

      wrapper.vm.handlePitchingChangeSubmit(testPayload)
      await wrapper.vm.$nextTick()

      expect(wrapper.emitted()).toHaveProperty('pitchingChange')
      expect(wrapper.emitted('pitchingChange')![0]).toEqual([testPayload])
    })

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

      wrapper.vm.handleCancel()
      await wrapper.vm.$nextTick()

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

  describe('Status Management', () => {
    it('shows active status when tab selected', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const pinchHitterTab = tabs.find(tab => tab.text().includes('Pinch Hitter'))
      await pinchHitterTab!.trigger('click')
      await wrapper.vm.$nextTick()

      expect(wrapper.vm.statusClass).toBe('status-active')
      expect(wrapper.vm.statusText).toBe('Active')
    })

    it('shows success status after successful submission', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const testPayload = {
        playerOutLineupId: 1,
        playerInCardId: 201,
        teamId: 1,
      }

      wrapper.vm.handlePinchHitterSubmit(testPayload)
      await wrapper.vm.$nextTick()

      expect(wrapper.vm.statusClass).toBe('status-success')
      expect(wrapper.vm.statusText).toBe('Success')
    })

    it('shows idle status by default', () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      expect(wrapper.vm.statusClass).toBe('status-idle')
      expect(wrapper.vm.statusText).toBe('Idle')
    })
  })

  describe('Success Messages', () => {
    it('displays success message after pinch hitter submission', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const testPayload = {
        playerOutLineupId: 1,
        playerInCardId: 201,
        teamId: 1,
      }

      wrapper.vm.handlePinchHitterSubmit(testPayload)
      await wrapper.vm.$nextTick()

      expect(wrapper.text()).toContain('Pinch hitter substitution submitted')
    })

    it('displays success message after defensive replacement', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const testPayload = {
        playerOutLineupId: 2,
        playerInCardId: 203,
        newPosition: '2B',
        teamId: 1,
      }

      wrapper.vm.handleDefensiveReplacementSubmit(testPayload)
      await wrapper.vm.$nextTick()

      expect(wrapper.text()).toContain('Defensive replacement submitted')
    })

    it('displays success message after pitching change', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const testPayload = {
        playerOutLineupId: 1,
        playerInCardId: 201,
        teamId: 1,
      }

      wrapper.vm.handlePitchingChangeSubmit(testPayload)
      await wrapper.vm.$nextTick()

      expect(wrapper.text()).toContain('Pitching change submitted')
    })
  })

  describe('State Reset', () => {
    it('resets to idle after cancel', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      const tabs = wrapper.findAll('.tab-button')
      const pinchHitterTab = tabs.find(tab => tab.text().includes('Pinch Hitter'))
      await pinchHitterTab!.trigger('click')
      expect(wrapper.vm.currentTab).toBe('pinch_hitter')

      wrapper.vm.handleCancel()
      await wrapper.vm.$nextTick()

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

    it('clears error when changing tabs', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      wrapper.vm.error = 'Test error'
      await wrapper.vm.$nextTick()

      const tabs = wrapper.findAll('.tab-button')
      const pinchHitterTab = tabs.find(tab => tab.text().includes('Pinch Hitter'))
      await pinchHitterTab!.trigger('click')

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

    it('clears defensive player selection when switching away from defensive tab', async () => {
      const wrapper = mount(SubstitutionPanel, {
        props: defaultProps,
      })

      wrapper.vm.selectedDefensivePlayer = mockCurrentLineup[1]
      await wrapper.vm.$nextTick()

      const tabs = wrapper.findAll('.tab-button')
      const pinchHitterTab = tabs.find(tab => tab.text().includes('Pinch Hitter'))
      await pinchHitterTab!.trigger('click')

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

  describe('Edge Cases', () => {
    it('handles empty bench players gracefully', () => {
      const wrapper = mount(SubstitutionPanel, {
        props: {
          ...defaultProps,
          benchPlayers: [],
        },
      })

      expect(wrapper.exists()).toBe(true)
    })

    it('handles missing currentPitcher', () => {
      const wrapper = mount(SubstitutionPanel, {
        props: {
          ...defaultProps,
          currentPitcher: null,
        },
      })

      expect(wrapper.exists()).toBe(true)
    })

    it('handles missing currentBatter', () => {
      const wrapper = mount(SubstitutionPanel, {
        props: {
          ...defaultProps,
          currentBatter: null,
        },
      })

      expect(wrapper.exists()).toBe(true)
    })
  })
})
