import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'

import {
  getDeviceFingerprint,
  clearDeviceFingerprint,
} from './device-fingerprint'

describe('device-fingerprint', () => {
  // 保存原始 navigator
  const originalNavigator = global.navigator

  beforeEach(() => {
    // 清除缓存
    clearDeviceFingerprint()
    vi.clearAllMocks()
  })

  afterEach(() => {
    clearDeviceFingerprint()
    global.navigator = originalNavigator
  })

  describe('getDeviceFingerprint', () => {
    it('should return a device fingerprint object', () => {
      const fingerprint = getDeviceFingerprint()

      expect(fingerprint).toBeDefined()
      expect(fingerprint).toHaveProperty('device_id')
      expect(fingerprint).toHaveProperty('device_name')
      expect(fingerprint).toHaveProperty('device_browser')
      expect(fingerprint).toHaveProperty('device_os')
    })

    it('should return the same fingerprint on multiple calls (singleton)', () => {
      const fingerprint1 = getDeviceFingerprint()
      const fingerprint2 = getDeviceFingerprint()

      expect(fingerprint1).toBe(fingerprint2)
      expect(fingerprint1.device_id).toBe(fingerprint2.device_id)
    })

    it('should return valid device_id', () => {
      const fingerprint = getDeviceFingerprint()

      expect(fingerprint.device_id).toBeTruthy()
      expect(typeof fingerprint.device_id).toBe('string')
      expect(fingerprint.device_id.length).toBeGreaterThan(0)
    })

    it('should return valid device_name format', () => {
      const fingerprint = getDeviceFingerprint()

      expect(fingerprint.device_name).toBeTruthy()
      expect(typeof fingerprint.device_name).toBe('string')
      // device_name 格式: "Browser on OS"
      expect(fingerprint.device_name).toMatch(/.+\s+on\s+.+/)
    })

    it('should return valid device_browser', () => {
      const fingerprint = getDeviceFingerprint()

      expect(fingerprint.device_browser).toBeTruthy()
      expect(typeof fingerprint.device_browser).toBe('string')
    })

    it('should return valid device_os', () => {
      const fingerprint = getDeviceFingerprint()

      expect(fingerprint.device_os).toBeTruthy()
      expect(typeof fingerprint.device_os).toBe('string')
    })
  })

  describe('clearDeviceFingerprint', () => {
    it('should clear cached fingerprint', () => {
      // 先获取一次生成缓存
      const fingerprint1 = getDeviceFingerprint()

      // 清除缓存
      clearDeviceFingerprint()

      // 再次获取应该是新的指纹
      const fingerprint2 = getDeviceFingerprint()

      // 两个指纹不应该相同
      expect(fingerprint1.device_id).not.toBe(fingerprint2.device_id)
    })

    it('should allow multiple clears without error', () => {
      clearDeviceFingerprint()
      clearDeviceFingerprint()
      clearDeviceFingerprint()

      // 不应该抛出错误
      expect(true).toBe(true)
    })
  })

  describe('browser detection', () => {
    it('should detect browser from user agent', () => {
      // 注意：实际测试中 navigator.userAgent 是只读的
      // 这里主要验证函数能正常工作
      const fingerprint = getDeviceFingerprint()
      expect(fingerprint.device_browser).toBeTruthy()
    })
  })

  describe('OS detection', () => {
    it('should detect OS from user agent', () => {
      // 类似浏览器检测，验证函数能正常工作
      const fingerprint = getDeviceFingerprint()
      expect(fingerprint.device_os).toBeTruthy()
    })
  })

  describe('security considerations', () => {
    it('should not store fingerprint in localStorage', () => {
      getDeviceFingerprint()

      // 设备指纹不应该存储在 localStorage
      const deviceId = localStorage.getItem('device_id')
      const fingerprint = localStorage.getItem('device_fingerprint')
      expect(deviceId).toBeFalsy() // null or undefined
      expect(fingerprint).toBeFalsy()
    })

    it('should not store fingerprint in sessionStorage', () => {
      getDeviceFingerprint()

      // 设备指纹不应该存储在 sessionStorage
      const deviceId = sessionStorage.getItem('device_id')
      const fingerprint = sessionStorage.getItem('device_fingerprint')
      expect(deviceId).toBeFalsy()
      expect(fingerprint).toBeFalsy()
    })
  })
})
