/**
 * Tests for file utilities
 * Run with: pnpm test file-utils
 */

import {
  encodeFileToBase64,
  decodeBase64ToBuffer,
  isBase64,
  detectMimeType,
  validateBase64File,
  encodeFileWithMetadata,
  sanitizeFilename,
  calculateFileHash,
  FILE_SIZE_LIMITS,
  SUPPORTED_MIME_TYPES,
} from './file-utils';

describe('File Utilities', () => {
  describe('encodeFileToBase64', () => {
    it('should encode buffer to base64', () => {
      const buffer = Buffer.from('test content');
      const result = encodeFileToBase64(buffer);
      expect(result).toBe('dGVzdCBjb250ZW50');
    });

    it('should encode string to base64', () => {
      const result = encodeFileToBase64('test content');
      expect(result).toBe('dGVzdCBjb250ZW50');
    });

    it('should return base64 string as-is if already encoded', () => {
      const base64 = 'dGVzdCBjb250ZW50';
      const result = encodeFileToBase64(base64);
      expect(result).toBe(base64);
    });

    it('should include MIME type in data URL format', () => {
      const buffer = Buffer.from('test');
      const result = encodeFileToBase64(buffer, 'application/json');
      expect(result).toContain('data:application/json;base64,');
    });
  });

  describe('decodeBase64ToBuffer', () => {
    it('should decode base64 to buffer', () => {
      const base64 = 'dGVzdCBjb250ZW50';
      const buffer = decodeBase64ToBuffer(base64);
      expect(buffer.toString()).toBe('test content');
    });

    it('should handle data URL format', () => {
      const dataUrl = 'data:application/json;base64,dGVzdCBjb250ZW50';
      const buffer = decodeBase64ToBuffer(dataUrl);
      expect(buffer.toString()).toBe('test content');
    });
  });

  describe('isBase64', () => {
    it('should return true for valid base64', () => {
      expect(isBase64('dGVzdCBjb250ZW50')).toBe(true);
      expect(isBase64('SGVsbG8gV29ybGQ=')).toBe(true);
    });

    it('should return false for invalid base64', () => {
      expect(isBase64('not base64!@#')).toBe(false);
      expect(isBase64('')).toBe(false);
    });

    it('should handle data URL format', () => {
      expect(isBase64('data:application/json;base64,dGVzdA==')).toBe(true);
    });
  });

  describe('detectMimeType', () => {
    it('should detect PDF from buffer', () => {
      const pdfBuffer = Buffer.from('%PDF-1.4\n');
      const mimeType = detectMimeType(pdfBuffer);
      expect(mimeType).toBe(SUPPORTED_MIME_TYPES.PDF);
    });

    it('should detect PNG from buffer', () => {
      const pngBuffer = Buffer.from([0x89, 0x50, 0x4E, 0x47]);
      const mimeType = detectMimeType(pngBuffer);
      expect(mimeType).toBe(SUPPORTED_MIME_TYPES.PNG);
    });

    it('should detect MIME type from filename', () => {
      const mimeType = detectMimeType(Buffer.from('test'), 'document.pdf');
      expect(mimeType).toBe(SUPPORTED_MIME_TYPES.PDF);
    });
  });

  describe('validateBase64File', () => {
    it('should validate valid base64 file', () => {
      const base64 = encodeFileToBase64(Buffer.from('test content'));
      const result = validateBase64File(base64);
      expect(result.valid).toBe(true);
      expect(result.errors).toHaveLength(0);
    });

    it('should reject invalid base64', () => {
      const result = validateBase64File('invalid base64!@#');
      expect(result.valid).toBe(false);
      expect(result.errors.length).toBeGreaterThan(0);
    });

    it('should enforce size limits', () => {
      const largeBuffer = Buffer.alloc(FILE_SIZE_LIMITS.MEDIUM + 1);
      const base64 = encodeFileToBase64(largeBuffer);
      const result = validateBase64File(base64, {
        maxSize: FILE_SIZE_LIMITS.MEDIUM,
      });
      expect(result.valid).toBe(false);
      expect(result.errors.some(e => e.includes('exceeds maximum'))).toBe(true);
    });

    it('should validate MIME types', () => {
      const pdfBuffer = Buffer.from('%PDF-1.4\n');
      const base64 = encodeFileToBase64(pdfBuffer);
      const result = validateBase64File(base64, {
        allowedMimeTypes: [SUPPORTED_MIME_TYPES.PDF],
      });
      expect(result.valid).toBe(true);
    });

    it('should reject disallowed MIME types', () => {
      const pdfBuffer = Buffer.from('%PDF-1.4\n');
      const base64 = encodeFileToBase64(pdfBuffer);
      const result = validateBase64File(base64, {
        allowedMimeTypes: [SUPPORTED_MIME_TYPES.PNG],
      });
      expect(result.valid).toBe(false);
    });
  });

  describe('sanitizeFilename', () => {
    it('should sanitize unsafe characters', () => {
      const filename = '../../etc/passwd';
      const sanitized = sanitizeFilename(filename);
      expect(sanitized).not.toContain('/');
      expect(sanitized).not.toContain('..');
    });

    it('should preserve safe characters', () => {
      const filename = 'document_123.pdf';
      const sanitized = sanitizeFilename(filename);
      expect(sanitized).toBe('document_123.pdf');
    });

    it('should limit filename length', () => {
      const longFilename = 'a'.repeat(300) + '.pdf';
      const sanitized = sanitizeFilename(longFilename);
      expect(sanitized.length).toBeLessThanOrEqual(255);
    });
  });

  describe('calculateFileHash', () => {
    it('should calculate SHA256 hash', () => {
      const data = Buffer.from('test content');
      const hash = calculateFileHash(data);
      expect(hash).toHaveLength(64); // SHA256 produces 64 hex characters
      expect(typeof hash).toBe('string');
    });

    it('should calculate SHA512 hash', () => {
      const data = Buffer.from('test content');
      const hash = calculateFileHash(data, 'sha512');
      expect(hash).toHaveLength(128); // SHA512 produces 128 hex characters
    });
  });
});

