/**
 * Tests for Sanitize Utility
 * FE-TEST-004: Test sanitize utility functions
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import {
  sanitizeHTML,
  sanitizeChatMessage,
  sanitizeTextInput,
  sanitizeURL,
  sanitizeEmail,
  validatePassword,
} from './sanitize';

// Mock DOMPurify
vi.mock('dompurify', () => ({
  default: {
    isSupported: true,
    sanitize: vi.fn((html: string) =>
      html.replace(/<script[^>]*>.*?<\/script>/gi, ''),
    ),
  },
}));

describe('sanitize utilities', () => {
  describe('sanitizeHTML', () => {
    it('should remove script tags', () => {
      const input = '<p>Hello</p><script>alert("xss")</script>';
      const result = sanitizeHTML(input);
      expect(result).not.toContain('<script>');
    });

    it('should escape HTML tags (sanitizeHTML escapes all HTML)', () => {
      const input = '<p>Hello <strong>world</strong></p>';
      const result = sanitizeHTML(input);
      // sanitizeHTML escapes all HTML, so tags become entities
      expect(result).toContain('&lt;');
      expect(result).toContain('Hello');
    });

    it('should remove dangerous patterns', () => {
      const input = '<p onclick="alert(1)">Hello</p>';
      const result = sanitizeHTML(input);
      expect(result).not.toContain('onclick');
    });
  });

  describe('sanitizeChatMessage', () => {
    it('should sanitize chat messages', () => {
      const input = '<p>Hello <script>alert("xss")</script></p>';
      const result = sanitizeChatMessage(input);
      expect(result).not.toContain('<script>');
    });

    it('should preserve basic formatting', () => {
      const input = '<p>Hello <strong>world</strong></p>';
      const result = sanitizeChatMessage(input);
      expect(result).toContain('<p>');
      expect(result).toContain('<strong>');
    });
  });

  describe('sanitizeTextInput', () => {
    it('should escape HTML', () => {
      const input = '<script>alert("xss")</script>';
      const result = sanitizeTextInput(input);
      expect(result).not.toContain('<script>');
      expect(result).toContain('&lt;');
    });

    it('should trim input', () => {
      expect(sanitizeTextInput('  hello  ')).toBe('hello');
    });
  });

  describe('sanitizeURL', () => {
    it('should allow http URLs', () => {
      const result = sanitizeURL('http://example.com');
      // URL.toString() adds trailing slash
      expect(result).toBe('http://example.com/');
    });

    it('should allow https URLs', () => {
      const result = sanitizeURL('https://example.com');
      // URL.toString() adds trailing slash
      expect(result).toBe('https://example.com/');
    });

    it('should reject javascript URLs', () => {
      const result = sanitizeURL('javascript:alert(1)');
      expect(result).toBeNull();
    });

    it('should reject file URLs', () => {
      const result = sanitizeURL('file:///etc/passwd');
      expect(result).toBeNull();
    });

    it('should return null for invalid URLs', () => {
      const result = sanitizeURL('not-a-url');
      expect(result).toBeNull();
    });
  });

  describe('sanitizeEmail', () => {
    it('should validate and normalize valid email', () => {
      const result = sanitizeEmail('Test@Example.COM');
      expect(result).toBe('test@example.com');
    });

    it('should return null for invalid email', () => {
      expect(sanitizeEmail('not-an-email')).toBeNull();
      expect(sanitizeEmail('test@')).toBeNull();
      expect(sanitizeEmail('@example.com')).toBeNull();
    });
  });

  describe('validatePassword', () => {
    it('should validate strong password', () => {
      const result = validatePassword('StrongP@ssw0rd123');
      expect(result.isValid).toBe(true);
      expect(result.errors).toHaveLength(0);
    });

    it('should reject short password', () => {
      const result = validatePassword('Short1!');
      expect(result.isValid).toBe(false);
      expect(result.errors.length).toBeGreaterThan(0);
    });

    it('should reject password without uppercase', () => {
      const result = validatePassword('lowercase123!');
      expect(result.isValid).toBe(false);
      expect(result.errors.some((e) => e.includes('majuscule'))).toBe(true);
    });

    it('should reject password without lowercase', () => {
      const result = validatePassword('UPPERCASE123!');
      expect(result.isValid).toBe(false);
      expect(result.errors.some((e) => e.includes('minuscule'))).toBe(true);
    });

    it('should reject password without number', () => {
      const result = validatePassword('NoNumber!');
      expect(result.isValid).toBe(false);
      expect(result.errors.some((e) => e.includes('chiffre'))).toBe(true);
    });

    it('should reject password without special character', () => {
      const result = validatePassword('NoSpecial123');
      expect(result.isValid).toBe(false);
      expect(result.errors.some((e) => e.includes('spécial'))).toBe(true);
    });

    it('should reject common weak patterns', () => {
      const result = validatePassword('Password123!');
      expect(result.isValid).toBe(false);
      expect(result.errors.some((e) => e.includes('commun'))).toBe(true);
    });
  });
});
