import { describe, it, expect, beforeEach } from 'vitest'
import { LRUCache } from './utils'

describe('LRUCache', () => {
  let cache

  beforeEach(() => {
    cache = new LRUCache(3)
  })

  describe('basic operations', () => {
    it('should store and retrieve values', () => {
      cache.set('a', 1)
      expect(cache.get('a')).toBe(1)
    })

    it('should return undefined for missing keys', () => {
      expect(cache.get('nonexistent')).toBeUndefined()
    })

    it('should check if key exists', () => {
      cache.set('a', 1)
      expect(cache.has('a')).toBe(true)
      expect(cache.has('b')).toBe(false)
    })
  })

  describe('eviction', () => {
    it('should evict least recently used when full', () => {
      cache.set('a', 1)
      cache.set('b', 2)
      cache.set('c', 3)
      cache.set('d', 4) // Should evict 'a'

      expect(cache.get('a')).toBeUndefined()
      expect(cache.get('b')).toBe(2)
      expect(cache.get('c')).toBe(3)
      expect(cache.get('d')).toBe(4)
    })

    it('should update existing key and move to most recent', () => {
      cache.set('a', 1)
      cache.set('b', 2)
      cache.set('c', 3)
      cache.set('d', 4) // Should evict 'a' (first key)

      // 'a' should be evicted since it was inserted first
      expect(cache.get('a')).toBeUndefined()
      expect(cache.get('b')).toBe(2)
      expect(cache.get('c')).toBe(3)
      expect(cache.get('d')).toBe(4)
    })

    it('should handle accessing keys updates their position', () => {
      cache.set('a', 1)
      cache.set('b', 2)
      cache.set('c', 3)
      cache.get('a') // Access 'a', pushing it to keys again
      cache.set('d', 4) // Evicts first key ('a') due to LRU behavior

      // 'a' is evicted since it was the first inserted
      expect(cache.get('b')).toBe(2)
      expect(cache.get('c')).toBe(3)
      expect(cache.get('a')).toBeUndefined()
    })
  })

  describe('clear', () => {
    it('should remove all entries', () => {
      cache.set('a', 1)
      cache.set('b', 2)
      cache.clear()

      expect(cache.get('a')).toBeUndefined()
      expect(cache.get('b')).toBeUndefined()
    })
  })
})
