import { describe, it, expect, beforeEach } from 'vitest'
import { mount } from '@vue/test-utils'
import DefensiveSetup from '~/components/Decisions/DefensiveSetup.vue'
import type { DefensiveDecision } from '~/types/game'

describe('DefensiveSetup', () => {
  const defaultProps = {
    gameId: 'test-game-123',
    isActive: true,
  }

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

      expect(wrapper.text()).toContain('Defensive Setup')
    })

    it('shows opponent turn indicator when not active', () => {
      const wrapper = mount(DefensiveSetup, {
        props: {
          ...defaultProps,
          isActive: false,
        },
      })

      expect(wrapper.text()).toContain("Opponent's Turn")
    })

    it('renders all form sections', () => {
      const wrapper = mount(DefensiveSetup, {
        props: defaultProps,
      })

      expect(wrapper.text()).toContain('Infield Depth')
      expect(wrapper.text()).toContain('Outfield Depth')
      expect(wrapper.text()).toContain('Hold Runners')
    })
  })

  describe('Initial Values', () => {
    it('uses default values when no currentSetup provided', () => {
      const wrapper = mount(DefensiveSetup, {
        props: defaultProps,
      })

      // Check preview shows defaults
      expect(wrapper.text()).toContain('Normal')
    })

    it('uses provided currentSetup values', () => {
      const currentSetup: DefensiveDecision = {
        infield_depth: 'back',
        outfield_depth: 'normal',
        hold_runners: [1, 3],
      }

      const wrapper = mount(DefensiveSetup, {
        props: {
          ...defaultProps,
          currentSetup,
        },
      })

      expect(wrapper.vm.localSetup.infield_depth).toBe('back')
      expect(wrapper.vm.localSetup.outfield_depth).toBe('normal')
      expect(wrapper.vm.localSetup.hold_runners).toEqual([1, 3])
    })
  })

  describe('Hold Runners', () => {
    it('initializes hold runner toggles from currentSetup', () => {
      const wrapper = mount(DefensiveSetup, {
        props: {
          ...defaultProps,
          currentSetup: {
            infield_depth: 'normal',
            outfield_depth: 'normal',
            hold_runners: [1, 2],
          },
        },
      })

      expect(wrapper.vm.holdFirst).toBe(true)
      expect(wrapper.vm.holdSecond).toBe(true)
      expect(wrapper.vm.holdThird).toBe(false)
    })

    it('updates hold_runners array when toggles change', async () => {
      const wrapper = mount(DefensiveSetup, {
        props: defaultProps,
      })

      wrapper.vm.holdFirst = true
      wrapper.vm.holdThird = true
      await wrapper.vm.$nextTick()

      expect(wrapper.vm.localSetup.hold_runners).toContain(1)
      expect(wrapper.vm.localSetup.hold_runners).toContain(3)
      expect(wrapper.vm.localSetup.hold_runners).not.toContain(2)
    })
  })

  describe('Preview Display', () => {
    it('displays current infield depth in preview', () => {
      const wrapper = mount(DefensiveSetup, {
        props: {
          ...defaultProps,
          gameState: {
            on_third: 123,  // Need runner on third for infield_in option
          } as any,
          currentSetup: {
            infield_depth: 'infield_in',
            outfield_depth: 'normal',
            hold_runners: [],
          },
        },
      })

      expect(wrapper.text()).toContain('Infield In')
    })

    it('displays holding status for multiple runners', () => {
      const wrapper = mount(DefensiveSetup, {
        props: {
          ...defaultProps,
          currentSetup: {
            infield_depth: 'normal',
            outfield_depth: 'normal',
            hold_runners: [1, 2, 3],
          },
        },
      })

      const holdingText = wrapper.vm.holdingDisplay
      expect(holdingText).toContain('1st')
      expect(holdingText).toContain('2nd')
      expect(holdingText).toContain('3rd')
    })

    it('shows "None" when no runners held', () => {
      const wrapper = mount(DefensiveSetup, {
        props: defaultProps,
      })

      expect(wrapper.vm.holdingDisplay).toBe('None')
    })
  })

  describe('Form Submission', () => {
    it('emits submit event with current setup', async () => {
      const wrapper = mount(DefensiveSetup, {
        props: defaultProps,
      })

      wrapper.vm.localSetup = {
        infield_depth: 'in',
        outfield_depth: 'normal',
        hold_runners: [2],
      }

      await wrapper.find('form').trigger('submit.prevent')

      expect(wrapper.emitted('submit')).toBeTruthy()
      const emitted = wrapper.emitted('submit')![0][0] as DefensiveDecision
      expect(emitted.infield_depth).toBe('in')
      expect(emitted.outfield_depth).toBe('normal')
      expect(emitted.hold_runners).toEqual([2])
    })

    it('does not submit when not active', async () => {
      const wrapper = mount(DefensiveSetup, {
        props: {
          ...defaultProps,
          isActive: false,
        },
      })

      await wrapper.find('form').trigger('submit.prevent')
      expect(wrapper.emitted('submit')).toBeFalsy()
    })

    it('allows submit with no changes (keep setup)', async () => {
      const currentSetup: DefensiveDecision = {
        infield_depth: 'normal',
        outfield_depth: 'normal',
        hold_runners: [],
      }

      const wrapper = mount(DefensiveSetup, {
        props: {
          ...defaultProps,
          currentSetup,
        },
      })

      await wrapper.find('form').trigger('submit.prevent')
      // Component allows submitting same setup to confirm player's choice
      expect(wrapper.emitted('submit')).toBeTruthy()
      const emitted = wrapper.emitted('submit')![0][0] as DefensiveDecision
      expect(emitted).toEqual(currentSetup)
    })

    it('shows loading state during submission', async () => {
      const wrapper = mount(DefensiveSetup, {
        props: defaultProps,
      })

      // Trigger submission
      wrapper.vm.submitting = true
      await wrapper.vm.$nextTick()

      // Verify button is in loading state
      expect(wrapper.vm.submitting).toBe(true)
    })
  })

  describe('Submit Button State', () => {
    it('shows "Wait for Your Turn" when not active', () => {
      const wrapper = mount(DefensiveSetup, {
        props: {
          ...defaultProps,
          isActive: false,
        },
      })

      expect(wrapper.vm.submitButtonText).toBe('Wait for Your Turn')
    })

    it('shows "Submit (Keep Setup)" when setup unchanged', () => {
      const currentSetup: DefensiveDecision = {
        infield_depth: 'normal',
        outfield_depth: 'normal',
        hold_runners: [],
      }

      const wrapper = mount(DefensiveSetup, {
        props: {
          ...defaultProps,
          currentSetup,
        },
      })

      expect(wrapper.vm.submitButtonText).toBe('Submit (Keep Setup)')
    })

    it('shows "Submit Defensive Setup" when active with changes', () => {
      const wrapper = mount(DefensiveSetup, {
        props: defaultProps,
      })

      wrapper.vm.localSetup.infield_depth = 'back'
      expect(wrapper.vm.submitButtonText).toBe('Submit Defensive Setup')
    })
  })

  describe('Change Detection', () => {
    it('detects infield depth changes', () => {
      const wrapper = mount(DefensiveSetup, {
        props: {
          ...defaultProps,
          currentSetup: {
            infield_depth: 'normal',
            outfield_depth: 'normal',
            hold_runners: [],
          },
        },
      })

      expect(wrapper.vm.hasChanges).toBe(false)
      wrapper.vm.localSetup.infield_depth = 'back'
      expect(wrapper.vm.hasChanges).toBe(true)
    })

    it('detects hold runners changes', () => {
      const wrapper = mount(DefensiveSetup, {
        props: {
          ...defaultProps,
          currentSetup: {
            infield_depth: 'normal',
            outfield_depth: 'normal',
            hold_runners: [],
          },
        },
      })

      expect(wrapper.vm.hasChanges).toBe(false)
      wrapper.vm.localSetup.hold_runners = [1]
      expect(wrapper.vm.hasChanges).toBe(true)
    })
  })

  describe('Prop Updates', () => {
    it('updates local state when currentSetup prop changes', async () => {
      const wrapper = mount(DefensiveSetup, {
        props: defaultProps,
      })

      const newSetup: DefensiveDecision = {
        infield_depth: 'double_play',
        outfield_depth: 'normal',
        hold_runners: [1, 2, 3],
      }

      await wrapper.setProps({ currentSetup: newSetup })

      expect(wrapper.vm.localSetup.infield_depth).toBe('double_play')
      expect(wrapper.vm.localSetup.outfield_depth).toBe('normal')
      expect(wrapper.vm.localSetup.hold_runners).toEqual([1, 2, 3])
    })
  })

  describe('Disabled State', () => {
    it('disables all controls when not active', () => {
      const wrapper = mount(DefensiveSetup, {
        props: {
          ...defaultProps,
          isActive: false,
        },
      })

      const buttonGroups = wrapper.findAllComponents({ name: 'ButtonGroup' })
      buttonGroups.forEach(bg => {
        expect(bg.props('disabled')).toBe(true)
      })

      const toggles = wrapper.findAllComponents({ name: 'ToggleSwitch' })
      toggles.forEach(toggle => {
        expect(toggle.props('disabled')).toBe(true)
      })
    })
  })
})
