import { it, expect, vi, beforeEach, afterEach, describe } from 'vitest'
import { createKvBackend } from './kv.js'

function createFakeKv() {
  const store = new Map<string, { value: string; expirationTtl?: number }>()
  return {
    store,
    async get(key: string, _type?: string) {
      const entry = store.get(key)
      return entry?.value ?? null
    },
    async put(
      key: string,
      value: string,
      options?: { expirationTtl?: number },
    ) {
      store.set(key, { value, expirationTtl: options?.expirationTtl })
    },
    async delete(key: string) {
      store.delete(key)
    },
  }
}

describe('createKvBackend', () => {
  it('kv.get null → undefined', async () => {
    const backend = createKvBackend(createFakeKv() as never)
    await expect(backend.get('missing')).resolves.toBeUndefined()
  })

  it('set + get round-trip', async () => {
    const kv = createFakeKv()
    const backend = createKvBackend(kv as never)
    await backend.set('k', 'v')
    await expect(backend.get('k')).resolves.toBe('v')
  })

  it('ttl → expirationTtl on put', async () => {
    const kv = createFakeKv()
    const put = vi.spyOn(kv, 'put')
    const backend = createKvBackend(kv as never)
    await backend.set('k', 'v', 120)
    expect(put).toHaveBeenCalledWith('k', 'v', { expirationTtl: 120 })
  })

  it('del → kv.delete', async () => {
    const kv = createFakeKv()
    const del = vi.spyOn(kv, 'delete')
    const backend = createKvBackend(kv as never)
    await backend.del('k')
    expect(del).toHaveBeenCalledWith('k')
  })
})
