import { describe, it, expect, vi, beforeEach } from 'vitest';
import { generateFingerprint, generateFingerprintSync } from './fingerprint';

describe('fingerprint', () => {
  describe('generateFingerprint', () => {
    it('should generate a fingerprint with fp_ prefix', async () => {
      const fingerprint = await generateFingerprint();

      expect(fingerprint).toMatch(/^fp_[a-f0-9]{32}$/);
    });

    it('should generate consistent fingerprints for same environment', async () => {
      const fp1 = await generateFingerprint();
      const fp2 = await generateFingerprint();

      expect(fp1).toBe(fp2);
    });

    it('should include browser detection in fingerprint components', async () => {
      // Chrome is in the mocked userAgent
      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();
    });
  });

  describe('generateFingerprintSync', () => {
    it('should generate a fingerprint with fp_ prefix', () => {
      const fingerprint = generateFingerprintSync();

      expect(fingerprint).toMatch(/^fp_[a-f0-9]+$/);
    });

    it('should be consistent for same environment', () => {
      const fp1 = generateFingerprintSync();
      const fp2 = generateFingerprintSync();

      expect(fp1).toBe(fp2);
    });
  });

  describe('environment variations', () => {
    it('should detect screen categories correctly', async () => {
      // Default is 1920px (FHD)
      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();
    });

    it('should handle touch detection', async () => {
      Object.defineProperty(navigator, 'maxTouchPoints', {
        value: 5,
        configurable: true,
      });

      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();

      // Reset
      Object.defineProperty(navigator, 'maxTouchPoints', {
        value: 0,
        configurable: true,
      });
    });

    it('should handle Do Not Track', async () => {
      Object.defineProperty(navigator, 'doNotTrack', {
        value: '1',
        configurable: true,
      });

      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();

      // Reset
      Object.defineProperty(navigator, 'doNotTrack', {
        value: null,
        configurable: true,
      });
    });
  });

  describe('browser detection', () => {
    it('should detect Firefox', async () => {
      Object.defineProperty(navigator, 'userAgent', {
        value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
        configurable: true,
      });

      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();

      // Reset
      Object.defineProperty(navigator, 'userAgent', {
        value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        configurable: true,
      });
    });

    it('should detect Safari', async () => {
      Object.defineProperty(navigator, 'userAgent', {
        value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15',
        configurable: true,
      });

      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();

      // Reset
      Object.defineProperty(navigator, 'userAgent', {
        value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        configurable: true,
      });
    });

    it('should detect Edge', async () => {
      Object.defineProperty(navigator, 'userAgent', {
        value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
        configurable: true,
      });

      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();

      // Reset
      Object.defineProperty(navigator, 'userAgent', {
        value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        configurable: true,
      });
    });
  });

  describe('platform detection', () => {
    it('should detect Windows', async () => {
      Object.defineProperty(navigator, 'platform', {
        value: 'Win32',
        configurable: true,
      });

      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();

      // Reset
      Object.defineProperty(navigator, 'platform', {
        value: 'MacIntel',
        configurable: true,
      });
    });

    it('should detect Linux', async () => {
      Object.defineProperty(navigator, 'platform', {
        value: 'Linux x86_64',
        configurable: true,
      });

      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();

      // Reset
      Object.defineProperty(navigator, 'platform', {
        value: 'MacIntel',
        configurable: true,
      });
    });

    it('should detect iOS', async () => {
      Object.defineProperty(navigator, 'platform', {
        value: 'iPhone',
        configurable: true,
      });

      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();

      // Reset
      Object.defineProperty(navigator, 'platform', {
        value: 'MacIntel',
        configurable: true,
      });
    });
  });

  describe('screen categories', () => {
    it('should detect 4K screens', async () => {
      Object.defineProperty(window, 'screen', {
        value: { width: 3840, height: 2160, colorDepth: 24 },
        configurable: true,
      });

      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();

      // Reset
      Object.defineProperty(window, 'screen', {
        value: { width: 1920, height: 1080, colorDepth: 24 },
        configurable: true,
      });
    });

    it('should detect tablet screens', async () => {
      Object.defineProperty(window, 'screen', {
        value: { width: 1024, height: 768, colorDepth: 24 },
        configurable: true,
      });

      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();

      // Reset
      Object.defineProperty(window, 'screen', {
        value: { width: 1920, height: 1080, colorDepth: 24 },
        configurable: true,
      });
    });

    it('should detect mobile screens', async () => {
      Object.defineProperty(window, 'screen', {
        value: { width: 375, height: 812, colorDepth: 24 },
        configurable: true,
      });

      const fingerprint = await generateFingerprint();
      expect(fingerprint).toBeDefined();

      // Reset
      Object.defineProperty(window, 'screen', {
        value: { width: 1920, height: 1080, colorDepth: 24 },
        configurable: true,
      });
    });
  });
});
