import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import StolenBaseInputs from '~/components/Decisions/StolenBaseInputs.vue'

describe('StolenBaseInputs', () => {
  const defaultProps = {
    runners: {
      first: null,
      second: null,
      third: null,
    },
    isActive: true,
  }

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

      expect(wrapper.text()).toContain('Stolen Base Attempts')
    })

    it('shows empty state when no runners', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: defaultProps,
      })

      expect(wrapper.text()).toContain('No runners on base')
    })

    it('shows toggles when runners on base', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
        },
      })

      expect(wrapper.text()).toContain('Runner on 1st attempts steal')
    })

    it('renders mini diamond visualization', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: 102,
            third: null,
          },
        },
      })

      // Check for base elements in the diamond
      const bases = wrapper.findAll('.w-5.h-5.rounded-full')
      expect(bases.length).toBeGreaterThan(0)
    })
  })

  describe('Runner Detection', () => {
    it('detects no runners', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: defaultProps,
      })

      expect(wrapper.vm.hasRunners).toBe(false)
    })

    it('detects runner on first', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
        },
      })

      expect(wrapper.vm.hasRunners).toBe(true)
    })

    it('detects multiple runners', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: 102,
            third: 103,
          },
        },
      })

      expect(wrapper.vm.hasRunners).toBe(true)
    })
  })

  describe('Steal Toggles', () => {
    it('shows toggle for runner on first', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
        },
      })

      expect(wrapper.text()).toContain('Runner on 1st attempts steal to 2nd')
    })

    it('shows toggle for runner on second', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: null,
            second: 102,
            third: null,
          },
        },
      })

      expect(wrapper.text()).toContain('Runner on 2nd attempts steal to 3rd')
    })

    it('shows toggle for runner on third', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: null,
            second: null,
            third: 103,
          },
        },
      })

      expect(wrapper.text()).toContain('Runner on 3rd attempts steal home')
    })

    it('shows all toggles when bases loaded', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: 102,
            third: 103,
          },
        },
      })

      expect(wrapper.text()).toContain('Runner on 1st')
      expect(wrapper.text()).toContain('Runner on 2nd')
      expect(wrapper.text()).toContain('Runner on 3rd')
    })
  })

  describe('Steal Attempts Calculation', () => {
    it('calculates empty steal attempts by default', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
        },
      })

      expect(wrapper.vm.stealAttempts).toEqual([])
    })

    it('calculates steal to second when first base toggle is on', async () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
        },
      })

      wrapper.vm.stealToSecond = true
      await wrapper.vm.$nextTick()

      expect(wrapper.vm.stealAttempts).toContain(2)
    })

    it('calculates steal to third when second base toggle is on', async () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: null,
            second: 102,
            third: null,
          },
        },
      })

      wrapper.vm.stealToThird = true
      await wrapper.vm.$nextTick()

      expect(wrapper.vm.stealAttempts).toContain(3)
    })

    it('calculates steal home when third base toggle is on', async () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: null,
            second: null,
            third: 103,
          },
        },
      })

      wrapper.vm.stealHome = true
      await wrapper.vm.$nextTick()

      expect(wrapper.vm.stealAttempts).toContain(4)
    })

    it('calculates multiple steal attempts', async () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: 102,
            third: 103,
          },
        },
      })

      wrapper.vm.stealToSecond = true
      wrapper.vm.stealHome = true
      await wrapper.vm.$nextTick()

      expect(wrapper.vm.stealAttempts).toContain(2)
      expect(wrapper.vm.stealAttempts).toContain(4)
      expect(wrapper.vm.stealAttempts.length).toBe(2)
    })

    it('does not include steal if no runner on that base', async () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: null,
            second: 102,
            third: null,
          },
        },
      })

      // Try to enable steal from first (no runner)
      wrapper.vm.stealToSecond = true
      await wrapper.vm.$nextTick()

      expect(wrapper.vm.stealAttempts).not.toContain(2)
    })
  })

  describe('Change Detection', () => {
    it('detects no changes when attempts match currentAttempts', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
          currentAttempts: [],
        },
      })

      expect(wrapper.vm.hasChanges).toBe(false)
    })

    it('detects changes when attempts differ', async () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
          currentAttempts: [],
        },
      })

      wrapper.vm.stealToSecond = true
      await wrapper.vm.$nextTick()

      expect(wrapper.vm.hasChanges).toBe(true)
    })
  })

  describe('Submit and Cancel', () => {
    it('emits submit with steal attempts', async () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: 102,
            third: null,
          },
        },
      })

      wrapper.vm.stealToSecond = true
      wrapper.vm.stealToThird = true
      await wrapper.vm.$nextTick()

      await wrapper.vm.handleSubmit()

      expect(wrapper.emitted('submit')).toBeTruthy()
      expect(wrapper.emitted('submit')![0]).toEqual([[2, 3]])
    })

    it('does not submit when not active', async () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          isActive: false,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
        },
      })

      await wrapper.vm.handleSubmit()
      expect(wrapper.emitted('submit')).toBeFalsy()
    })

    it('does not submit when no changes', async () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
          currentAttempts: [],
        },
      })

      await wrapper.vm.handleSubmit()
      expect(wrapper.emitted('submit')).toBeFalsy()
    })

    it('emits cancel event', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
        },
      })

      wrapper.vm.handleCancel()
      expect(wrapper.emitted('cancel')).toBeTruthy()
    })

    it('resets toggles on cancel', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
          currentAttempts: [2],
        },
      })

      // Change toggle
      wrapper.vm.stealToSecond = false

      // Cancel should reset
      wrapper.vm.handleCancel()
      expect(wrapper.vm.stealToSecond).toBe(true)
    })
  })

  describe('Submit Button Text', () => {
    it('shows wait message when not active', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          isActive: false,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
        },
      })

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

    it('shows no changes message', () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
          currentAttempts: [],
        },
      })

      expect(wrapper.vm.submitButtonText).toBe('No Changes')
    })

    it('shows no attempts message when no steals selected', async () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
          currentAttempts: [2],
        },
      })

      wrapper.vm.stealToSecond = false
      await wrapper.vm.$nextTick()

      expect(wrapper.vm.submitButtonText).toBe('No Steal Attempts')
    })

    it('shows count of attempts', async () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: 102,
            third: null,
          },
        },
      })

      wrapper.vm.stealToSecond = true
      wrapper.vm.stealToThird = true
      await wrapper.vm.$nextTick()

      expect(wrapper.vm.submitButtonText).toBe('Submit 2 Attempts')
    })
  })

  describe('Runner Changes', () => {
    it('clears steal toggle when runner removed from base', async () => {
      const wrapper = mount(StolenBaseInputs, {
        props: {
          ...defaultProps,
          runners: {
            first: 101,
            second: null,
            third: null,
          },
        },
      })

      wrapper.vm.stealToSecond = true
      await wrapper.vm.$nextTick()

      // Remove runner from first
      await wrapper.setProps({
        runners: {
          first: null,
          second: null,
          third: null,
        },
      })

      expect(wrapper.vm.stealToSecond).toBe(false)
    })
  })
})
