import { describe, it, expect } from 'vitest'

import {
  generateMobileSecret,
  generateDesktopToken,
  hashToken,
  verifyToken,
  isPairedSessionExpired,
} from '@/lib/auth/pairing'

describe('lib/auth/pairing', () => {
  describe('generateMobileSecret / generateDesktopToken', () => {
    it('produceert 43-karakter base64url (32 bytes)', () => {
      // 32 bytes → ceil(32/3) * 4 = 44 chars zonder padding → 43 chars in base64url (geen '=')
      expect(generateMobileSecret()).toMatch(/^[A-Za-z0-9_-]{43}$/)
      expect(generateDesktopToken()).toMatch(/^[A-Za-z0-9_-]{43}$/)
    })

    it('twee opeenvolgende calls leveren verschillende waardes', () => {
      const a = generateMobileSecret()
      const b = generateMobileSecret()
      expect(a).not.toBe(b)
    })

    it('mobile en desktop generators delen geen state — paren zijn onafhankelijk', () => {
      const m1 = generateMobileSecret()
      const d1 = generateDesktopToken()
      const m2 = generateMobileSecret()
      const d2 = generateDesktopToken()
      expect(new Set([m1, d1, m2, d2]).size).toBe(4)
    })
  })

  describe('hashToken', () => {
    it('is deterministisch — zelfde input → zelfde hash', () => {
      const t = 'voorbeeld-token'
      expect(hashToken(t)).toBe(hashToken(t))
    })

    it('produceert 64-karakter hex (sha256)', () => {
      expect(hashToken('x')).toMatch(/^[a-f0-9]{64}$/)
    })

    it('verschillende inputs → verschillende hashes', () => {
      expect(hashToken('a')).not.toBe(hashToken('b'))
    })
  })

  describe('verifyToken', () => {
    it('true voor geldig (token, hashOf(token))', () => {
      const token = generateMobileSecret()
      expect(verifyToken(token, hashToken(token))).toBe(true)
    })

    it('false voor onjuist token', () => {
      const realHash = hashToken('echt-token')
      expect(verifyToken('verkeerd-token', realHash)).toBe(false)
    })

    it('false bij hash met afwijkende lengte', () => {
      expect(verifyToken('iets', 'abc')).toBe(false)
    })

    it('false bij lege hash', () => {
      expect(verifyToken('iets', '')).toBe(false)
    })
  })

  describe('isPairedSessionExpired', () => {
    it('false als paired niet gezet is (reguliere wachtwoord-sessie)', () => {
      expect(isPairedSessionExpired({})).toBe(false)
    })

    it('false als pairedExpiresAt ontbreekt', () => {
      expect(isPairedSessionExpired({ paired: true })).toBe(false)
    })

    it('false als de paired-sessie nog niet vervallen is', () => {
      const future = Date.now() + 60_000
      expect(isPairedSessionExpired({ paired: true, pairedExpiresAt: future })).toBe(false)
    })

    it('true als paired én vervaltijd in het verleden ligt', () => {
      const past = Date.now() - 1_000
      expect(isPairedSessionExpired({ paired: true, pairedExpiresAt: past })).toBe(true)
    })
  })
})
