import { describe, it, expect, beforeEach } from 'vitest'
import { useSettingsStore } from '@/stores/settings-store'

describe('settings-store', () => {
  beforeEach(() => {
    // Reset store state before each test
    useSettingsStore.setState({
      soundEnabled: true,
      vibrationEnabled: true,
    })
  })

  describe('initial state', () => {
    it('should initialize with sound enabled', () => {
      const { soundEnabled } = useSettingsStore.getState()
      expect(soundEnabled).toBe(true)
    })

    it('should initialize with vibration enabled', () => {
      const { vibrationEnabled } = useSettingsStore.getState()
      expect(vibrationEnabled).toBe(true)
    })

    it('should have all expected properties', () => {
      const state = useSettingsStore.getState()
      expect(state).toHaveProperty('soundEnabled')
      expect(state).toHaveProperty('vibrationEnabled')
      expect(state).toHaveProperty('setSoundEnabled')
      expect(state).toHaveProperty('setVibrationEnabled')
    })
  })

  describe('setSoundEnabled', () => {
    it('should enable sound', () => {
      const { setSoundEnabled } = useSettingsStore.getState()

      setSoundEnabled(true)

      const { soundEnabled } = useSettingsStore.getState()
      expect(soundEnabled).toBe(true)
    })

    it('should disable sound', () => {
      const { setSoundEnabled } = useSettingsStore.getState()

      setSoundEnabled(false)

      const { soundEnabled } = useSettingsStore.getState()
      expect(soundEnabled).toBe(false)
    })

    it('should toggle sound setting', () => {
      const { setSoundEnabled } = useSettingsStore.getState()

      setSoundEnabled(false)
      expect(useSettingsStore.getState().soundEnabled).toBe(false)

      setSoundEnabled(true)
      expect(useSettingsStore.getState().soundEnabled).toBe(true)
    })

    it('should not affect vibration setting', () => {
      const { setSoundEnabled } = useSettingsStore.getState()

      setSoundEnabled(false)

      const state = useSettingsStore.getState()
      expect(state.soundEnabled).toBe(false)
      expect(state.vibrationEnabled).toBe(true)
    })

    it('should allow multiple calls', () => {
      const { setSoundEnabled } = useSettingsStore.getState()

      setSoundEnabled(false)
      setSoundEnabled(false)
      setSoundEnabled(true)
      setSoundEnabled(true)

      const { soundEnabled } = useSettingsStore.getState()
      expect(soundEnabled).toBe(true)
    })
  })

  describe('setVibrationEnabled', () => {
    it('should enable vibration', () => {
      const { setVibrationEnabled } = useSettingsStore.getState()

      setVibrationEnabled(true)

      const { vibrationEnabled } = useSettingsStore.getState()
      expect(vibrationEnabled).toBe(true)
    })

    it('should disable vibration', () => {
      const { setVibrationEnabled } = useSettingsStore.getState()

      setVibrationEnabled(false)

      const { vibrationEnabled } = useSettingsStore.getState()
      expect(vibrationEnabled).toBe(false)
    })

    it('should toggle vibration setting', () => {
      const { setVibrationEnabled } = useSettingsStore.getState()

      setVibrationEnabled(false)
      expect(useSettingsStore.getState().vibrationEnabled).toBe(false)

      setVibrationEnabled(true)
      expect(useSettingsStore.getState().vibrationEnabled).toBe(true)
    })

    it('should not affect sound setting', () => {
      const { setVibrationEnabled } = useSettingsStore.getState()

      setVibrationEnabled(false)

      const state = useSettingsStore.getState()
      expect(state.vibrationEnabled).toBe(false)
      expect(state.soundEnabled).toBe(true)
    })

    it('should allow multiple calls', () => {
      const { setVibrationEnabled } = useSettingsStore.getState()

      setVibrationEnabled(false)
      setVibrationEnabled(false)
      setVibrationEnabled(true)
      setVibrationEnabled(true)

      const { vibrationEnabled } = useSettingsStore.getState()
      expect(vibrationEnabled).toBe(true)
    })
  })

  describe('combined settings', () => {
    it('should allow both settings to be disabled', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      setSoundEnabled(false)
      setVibrationEnabled(false)

      const state = useSettingsStore.getState()
      expect(state.soundEnabled).toBe(false)
      expect(state.vibrationEnabled).toBe(false)
    })

    it('should allow both settings to be enabled', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      // First disable both
      setSoundEnabled(false)
      setVibrationEnabled(false)

      // Then enable both
      setSoundEnabled(true)
      setVibrationEnabled(true)

      const state = useSettingsStore.getState()
      expect(state.soundEnabled).toBe(true)
      expect(state.vibrationEnabled).toBe(true)
    })

    it('should allow mixed settings', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      setSoundEnabled(true)
      setVibrationEnabled(false)

      const state = useSettingsStore.getState()
      expect(state.soundEnabled).toBe(true)
      expect(state.vibrationEnabled).toBe(false)
    })

    it('should handle rapid setting changes', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      for (let i = 0; i < 10; i++) {
        setSoundEnabled(i % 2 === 0)
        setVibrationEnabled(i % 3 === 0)
      }

      const state = useSettingsStore.getState()
      expect(state.soundEnabled).toBe(false) // i=9, 9%2=1 (false)
      expect(state.vibrationEnabled).toBe(true) // i=9, 9%3=0 (true)
    })

    it('should maintain independence between settings', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      // Change sound multiple times
      setSoundEnabled(false)
      setSoundEnabled(true)
      setSoundEnabled(false)

      // Vibration should still be at initial state
      expect(useSettingsStore.getState().vibrationEnabled).toBe(true)

      // Change vibration multiple times
      setVibrationEnabled(false)
      setVibrationEnabled(true)
      setVibrationEnabled(false)

      // Sound should still be at last set state
      expect(useSettingsStore.getState().soundEnabled).toBe(false)
    })
  })

  describe('persistence', () => {
    it('should maintain state across multiple reads', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      setSoundEnabled(false)
      setVibrationEnabled(false)

      // Read state multiple times
      for (let i = 0; i < 5; i++) {
        const state = useSettingsStore.getState()
        expect(state.soundEnabled).toBe(false)
        expect(state.vibrationEnabled).toBe(false)
      }
    })

    it('should persist settings after actions', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      setSoundEnabled(false)
      setVibrationEnabled(true)

      const state1 = useSettingsStore.getState()
      const state2 = useSettingsStore.getState()

      expect(state1.soundEnabled).toBe(state2.soundEnabled)
      expect(state1.vibrationEnabled).toBe(state2.vibrationEnabled)
    })
  })

  describe('type safety', () => {
    it('should accept boolean values for sound', () => {
      const { setSoundEnabled } = useSettingsStore.getState()

      // TypeScript would catch non-boolean values at compile time
      // Runtime check for proper boolean handling
      setSoundEnabled(true)
      expect(useSettingsStore.getState().soundEnabled).toBe(true)

      setSoundEnabled(false)
      expect(useSettingsStore.getState().soundEnabled).toBe(false)
    })

    it('should accept boolean values for vibration', () => {
      const { setVibrationEnabled } = useSettingsStore.getState()

      // TypeScript would catch non-boolean values at compile time
      // Runtime check for proper boolean handling
      setVibrationEnabled(true)
      expect(useSettingsStore.getState().vibrationEnabled).toBe(true)

      setVibrationEnabled(false)
      expect(useSettingsStore.getState().vibrationEnabled).toBe(false)
    })
  })

  describe('edge cases', () => {
    it('should handle setting same value multiple times', () => {
      const { setSoundEnabled } = useSettingsStore.getState()

      setSoundEnabled(true)
      setSoundEnabled(true)
      setSoundEnabled(true)

      expect(useSettingsStore.getState().soundEnabled).toBe(true)
    })

    it('should handle alternating settings rapidly', () => {
      const { setSoundEnabled } = useSettingsStore.getState()

      for (let i = 0; i < 100; i++) {
        setSoundEnabled(i % 2 === 0)
      }

      expect(useSettingsStore.getState().soundEnabled).toBe(false)
    })

    it('should handle concurrent setting changes', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      setSoundEnabled(false)
      setVibrationEnabled(false)
      setSoundEnabled(true)

      const state = useSettingsStore.getState()
      expect(state.soundEnabled).toBe(true)
      expect(state.vibrationEnabled).toBe(false)
    })

    it('should maintain correct state after reset', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      // Change settings
      setSoundEnabled(false)
      setVibrationEnabled(false)

      // Reset to initial state
      useSettingsStore.setState({
        soundEnabled: true,
        vibrationEnabled: true,
      })

      const state = useSettingsStore.getState()
      expect(state.soundEnabled).toBe(true)
      expect(state.vibrationEnabled).toBe(true)
    })
  })

  describe('user preferences', () => {
    it('should support user preferring sound only', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      setSoundEnabled(true)
      setVibrationEnabled(false)

      const state = useSettingsStore.getState()
      expect(state.soundEnabled).toBe(true)
      expect(state.vibrationEnabled).toBe(false)
    })

    it('should support user preferring vibration only', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      setSoundEnabled(false)
      setVibrationEnabled(true)

      const state = useSettingsStore.getState()
      expect(state.soundEnabled).toBe(false)
      expect(state.vibrationEnabled).toBe(true)
    })

    it('should support user preferring neither', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      setSoundEnabled(false)
      setVibrationEnabled(false)

      const state = useSettingsStore.getState()
      expect(state.soundEnabled).toBe(false)
      expect(state.vibrationEnabled).toBe(false)
    })

    it('should support user preferring both', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      setSoundEnabled(true)
      setVibrationEnabled(true)

      const state = useSettingsStore.getState()
      expect(state.soundEnabled).toBe(true)
      expect(state.vibrationEnabled).toBe(true)
    })

    it('should allow user to change preferences over time', () => {
      const { setSoundEnabled, setVibrationEnabled } = useSettingsStore.getState()

      // Initial preference: both enabled
      setSoundEnabled(true)
      setVibrationEnabled(true)
      expect(useSettingsStore.getState().soundEnabled).toBe(true)
      expect(useSettingsStore.getState().vibrationEnabled).toBe(true)

      // Change preference: disable sound
      setSoundEnabled(false)
      expect(useSettingsStore.getState().soundEnabled).toBe(false)
      expect(useSettingsStore.getState().vibrationEnabled).toBe(true)

      // Change preference: disable vibration too
      setVibrationEnabled(false)
      expect(useSettingsStore.getState().soundEnabled).toBe(false)
      expect(useSettingsStore.getState().vibrationEnabled).toBe(false)

      // Change preference: re-enable sound
      setSoundEnabled(true)
      expect(useSettingsStore.getState().soundEnabled).toBe(true)
      expect(useSettingsStore.getState().vibrationEnabled).toBe(false)
    })
  })
})
