import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import ManualOutcomeEntry from '~/components/Gameplay/ManualOutcomeEntry.vue'
import type { RollData, PlayOutcome } from '~/types'

// TODO: Fix text rendering (lowercase vs capitalized) and DOM element selection issues
describe.skip('ManualOutcomeEntry', () => {
  const createRollData = (): RollData => ({
    roll_id: 'test-roll-123',
    d6_one: 3,
    d6_two_a: 2,
    d6_two_b: 4,
    d6_two_total: 6,
    chaos_d20: 15,
    resolution_d20: 8,
    check_wild_pitch: false,
    check_passed_ball: false,
    timestamp: '2025-01-13T12:00:00Z',
  })

  // ============================================================================
  // Rendering Tests
  // ============================================================================

  describe('Rendering', () => {
    it('renders outcome entry form', () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      expect(wrapper.find('.manual-outcome-entry').exists()).toBe(true)
      expect(wrapper.text()).toContain('Select Outcome')
    })

    it('renders all outcome categories', () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      expect(wrapper.text()).toContain('Outs')
      expect(wrapper.text()).toContain('Hits')
      expect(wrapper.text()).toContain('Walks / HBP')
      expect(wrapper.text()).toContain('Special')
      expect(wrapper.text()).toContain('Interrupts')
    })

    it('renders action buttons', () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const buttons = wrapper.findAll('.button')
      expect(buttons).toHaveLength(2)
      expect(wrapper.find('.button-cancel').text()).toBe('Cancel')
      expect(buttons[1].text()).toBe('Submit Outcome')
    })

    it('does not render hit location by default', () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      expect(wrapper.find('.hit-location-section').exists()).toBe(false)
    })
  })

  // ============================================================================
  // Outcome Selection Tests
  // ============================================================================

  describe('Outcome Selection', () => {
    it('selects outcome when button clicked', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const strikeoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Strikeout')
      )
      await strikeoutButton?.trigger('click')

      expect(strikeoutButton?.classes()).toContain('outcome-button-selected')
    })

    it('deselects previous outcome when new one selected', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const buttons = wrapper.findAll('.outcome-button')
      const strikeoutButton = buttons.find(btn => btn.text().includes('Strikeout'))
      const walkButton = buttons.find(btn => btn.text() === 'Walk')

      await strikeoutButton?.trigger('click')
      expect(strikeoutButton?.classes()).toContain('outcome-button-selected')

      await walkButton?.trigger('click')
      expect(strikeoutButton?.classes()).not.toContain('outcome-button-selected')
      expect(walkButton?.classes()).toContain('outcome-button-selected')
    })

    it('formats outcome names correctly', () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      expect(wrapper.text()).toContain('Hit By Pitch')
      expect(wrapper.text()).toContain('Intentional Walk')
      expect(wrapper.text()).toContain('Double Play')
    })
  })

  // ============================================================================
  // Hit Location Tests
  // ============================================================================

  describe('Hit Location', () => {
    it('shows hit location for GROUNDOUT', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const outcomeButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Groundout')
      )
      await outcomeButton?.trigger('click')

      expect(wrapper.find('.hit-location-section').exists()).toBe(true)
    })

    it('shows hit location for FLYOUT', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const outcomeButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Flyout')
      )
      await outcomeButton?.trigger('click')

      expect(wrapper.find('.hit-location-section').exists()).toBe(true)
    })

    it('shows hit location for SINGLE', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const outcomeButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text() === 'Single 1'
      )
      await outcomeButton?.trigger('click')

      expect(wrapper.find('.hit-location-section').exists()).toBe(true)
    })

    it('shows hit location for ERROR', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const outcomeButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Error')
      )
      await outcomeButton?.trigger('click')

      expect(wrapper.find('.hit-location-section').exists()).toBe(true)
    })

    it('hides hit location for strikeout', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const strikeoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Strikeout')
      )
      await strikeoutButton?.trigger('click')

      expect(wrapper.find('.hit-location-section').exists()).toBe(false)
    })

    it('renders all infield positions', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const groundoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Groundout')
      )
      await groundoutButton?.trigger('click')

      expect(wrapper.text()).toContain('P')
      expect(wrapper.text()).toContain('C')
      expect(wrapper.text()).toContain('1B')
      expect(wrapper.text()).toContain('2B')
      expect(wrapper.text()).toContain('3B')
      expect(wrapper.text()).toContain('SS')
    })

    it('renders all outfield positions', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const flyoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Flyout')
      )
      await flyoutButton?.trigger('click')

      expect(wrapper.text()).toContain('LF')
      expect(wrapper.text()).toContain('CF')
      expect(wrapper.text()).toContain('RF')
    })

    it('selects hit location when clicked', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const groundoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Groundout')
      )
      await groundoutButton?.trigger('click')

      const ssButton = wrapper.findAll('.location-button').find(btn =>
        btn.text() === 'SS'
      )
      await ssButton?.trigger('click')

      expect(ssButton?.classes()).toContain('location-button-selected')
    })

    it('clears hit location when outcome changes to one not needing location', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      // Select groundout (needs location)
      const groundoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Groundout')
      )
      await groundoutButton?.trigger('click')

      const ssButton = wrapper.findAll('.location-button').find(btn =>
        btn.text() === 'SS'
      )
      await ssButton?.trigger('click')

      // Select strikeout (doesn't need location)
      const strikeoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Strikeout')
      )
      await strikeoutButton?.trigger('click')

      expect(wrapper.find('.hit-location-section').exists()).toBe(false)
    })
  })

  // ============================================================================
  // Submit Button State Tests
  // ============================================================================

  describe('Submit Button State', () => {
    it('disables submit when no outcome selected', () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const submitButton = wrapper.findAll('.button')[1]
      expect(submitButton.classes()).toContain('button-submit-disabled')
      expect(submitButton.attributes('disabled')).toBeDefined()
    })

    it('enables submit when outcome selected (no location needed)', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const strikeoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Strikeout')
      )
      await strikeoutButton?.trigger('click')

      const submitButton = wrapper.findAll('.button')[1]
      expect(submitButton.classes()).toContain('button-submit')
      expect(submitButton.attributes('disabled')).toBeUndefined()
    })

    it('disables submit when outcome selected but location needed and not selected', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const groundoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Groundout')
      )
      await groundoutButton?.trigger('click')

      const submitButton = wrapper.findAll('.button')[1]
      expect(submitButton.classes()).toContain('button-submit-disabled')
      expect(submitButton.attributes('disabled')).toBeDefined()
    })

    it('enables submit when outcome and location both selected', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const groundoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Groundout')
      )
      await groundoutButton?.trigger('click')

      const ssButton = wrapper.findAll('.location-button').find(btn =>
        btn.text() === 'SS'
      )
      await ssButton?.trigger('click')

      const submitButton = wrapper.findAll('.button')[1]
      expect(submitButton.classes()).toContain('button-submit')
      expect(submitButton.attributes('disabled')).toBeUndefined()
    })

    it('disables submit when canSubmit prop is false', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: false,
        },
      })

      const strikeoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Strikeout')
      )
      await strikeoutButton?.trigger('click')

      const submitButton = wrapper.findAll('.button')[1]
      expect(submitButton.classes()).toContain('button-submit-disabled')
    })

    it('disables submit when rollData is null', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: null,
          canSubmit: true,
        },
      })

      const strikeoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Strikeout')
      )
      await strikeoutButton?.trigger('click')

      const submitButton = wrapper.findAll('.button')[1]
      expect(submitButton.classes()).toContain('button-submit-disabled')
    })
  })

  // ============================================================================
  // Event Emission Tests
  // ============================================================================

  describe('Event Emission', () => {
    it('emits submit event with outcome (no location)', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const strikeoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Strikeout')
      )
      await strikeoutButton?.trigger('click')
      await wrapper.findAll('.button')[1].trigger('click')

      expect(wrapper.emitted('submit')).toBeTruthy()
      expect(wrapper.emitted('submit')?.[0]).toEqual([{
        outcome: 'STRIKEOUT',
        hitLocation: undefined,
      }])
    })

    it('emits submit event with outcome and location', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const groundoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Groundout')
      )
      await groundoutButton?.trigger('click')

      const ssButton = wrapper.findAll('.location-button').find(btn =>
        btn.text() === 'SS'
      )
      await ssButton?.trigger('click')

      await wrapper.findAll('.button')[1].trigger('click')

      expect(wrapper.emitted('submit')).toBeTruthy()
      expect(wrapper.emitted('submit')?.[0]).toEqual([{
        outcome: 'GROUNDOUT',
        hitLocation: 'SS',
      }])
    })

    it('emits cancel event when cancel button clicked', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

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

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

    it('does not emit submit when form invalid', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      await wrapper.findAll('.button')[1].trigger('click')

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

    it('resets form after successful submit', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const strikeoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Strikeout')
      )
      await strikeoutButton?.trigger('click')
      await wrapper.findAll('.button')[1].trigger('click')

      expect(strikeoutButton?.classes()).not.toContain('outcome-button-selected')
    })

    it('resets form after cancel', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const strikeoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Strikeout')
      )
      await strikeoutButton?.trigger('click')
      await wrapper.find('.button-cancel').trigger('click')

      expect(strikeoutButton?.classes()).not.toContain('outcome-button-selected')
    })
  })

  // ============================================================================
  // Outcome Categories Tests
  // ============================================================================

  describe('Outcome Categories', () => {
    it('renders outs category outcomes', () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      expect(wrapper.text()).toContain('Strikeout')
      expect(wrapper.text()).toContain('Groundout')
      expect(wrapper.text()).toContain('Flyout')
      expect(wrapper.text()).toContain('Lineout')
      expect(wrapper.text()).toContain('Popout')
      expect(wrapper.text()).toContain('Double Play')
    })

    it('renders hits category outcomes', () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      expect(wrapper.text()).toContain('Single 1')
      expect(wrapper.text()).toContain('Single 2')
      expect(wrapper.text()).toContain('Double 2')
      expect(wrapper.text()).toContain('Triple')
      expect(wrapper.text()).toContain('Homerun')
    })

    it('renders walks category outcomes', () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      expect(wrapper.text()).toContain('Walk')
      expect(wrapper.text()).toContain('Intentional Walk')
      expect(wrapper.text()).toContain('Hit By Pitch')
    })

    it('renders special category outcomes', () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

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

    it('renders interrupts category outcomes', () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      expect(wrapper.text()).toContain('Stolen Base')
      expect(wrapper.text()).toContain('Caught Stealing')
      expect(wrapper.text()).toContain('Wild Pitch')
      expect(wrapper.text()).toContain('Passed Ball')
      expect(wrapper.text()).toContain('Balk')
      expect(wrapper.text()).toContain('Pick Off')
    })
  })

  // ============================================================================
  // Edge Cases
  // ============================================================================

  describe('Edge Cases', () => {
    it('handles multiple hit location changes', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const groundoutButton = wrapper.findAll('.outcome-button').find(btn =>
        btn.text().includes('Groundout')
      )
      await groundoutButton?.trigger('click')

      const ssButton = wrapper.findAll('.location-button').find(btn =>
        btn.text() === 'SS'
      )
      const cfButton = wrapper.findAll('.location-button').find(btn =>
        btn.text() === 'CF'
      )

      await ssButton?.trigger('click')
      expect(ssButton?.classes()).toContain('location-button-selected')

      await cfButton?.trigger('click')
      expect(ssButton?.classes()).not.toContain('location-button-selected')
      expect(cfButton?.classes()).toContain('location-button-selected')
    })

    it('handles rapid outcome selection changes', async () => {
      const wrapper = mount(ManualOutcomeEntry, {
        props: {
          rollData: createRollData(),
          canSubmit: true,
        },
      })

      const buttons = wrapper.findAll('.outcome-button')
      const strikeoutButton = buttons.find(btn => btn.text().includes('Strikeout'))
      const walkButton = buttons.find(btn => btn.text() === 'Walk')
      const homerunButton = buttons.find(btn => btn.text().includes('Homerun'))

      await strikeoutButton?.trigger('click')
      await walkButton?.trigger('click')
      await homerunButton?.trigger('click')

      expect(homerunButton?.classes()).toContain('outcome-button-selected')
      expect(strikeoutButton?.classes()).not.toContain('outcome-button-selected')
      expect(walkButton?.classes()).not.toContain('outcome-button-selected')
    })
  })
})
