import { ReturnToSanitizer } from './ReturnToSanitizer';

describe('ReturnToSanitizer', () => {
  let sanitizer: ReturnToSanitizer;

  beforeEach(() => {
    sanitizer = new ReturnToSanitizer();
  });

  describe('sanitizeReturnTo', () => {
    const FALLBACK = '/dashboard';

    it('should return fallback when input is null', () => {
      const result = sanitizer.sanitizeReturnTo(null, FALLBACK);
      expect(result).toBe(FALLBACK);
    });

    it('should return fallback when input is empty string', () => {
      const result = sanitizer.sanitizeReturnTo('', FALLBACK);
      expect(result).toBe(FALLBACK);
    });

    it('should return fallback when input is undefined', () => {
      const result = sanitizer.sanitizeReturnTo(undefined as any, FALLBACK);
      expect(result).toBe(FALLBACK);
    });

    it('should accept valid relative paths starting with /', () => {
      const validPaths = [
        '/dashboard',
        '/profile/settings',
        '/leagues/123',
        '/sponsor/dashboard',
        '/admin/users',
        '/',
      ];

      validPaths.forEach(path => {
        const result = sanitizer.sanitizeReturnTo(path, FALLBACK);
        expect(result).toBe(path);
      });
    });

    it('should strip protocol and host from absolute URLs', () => {
      const testCases = [
        { input: 'https://example.com/dashboard', expected: '/dashboard' },
        { input: 'http://example.com/profile', expected: '/profile' },
        { input: 'https://evil.com/steal', expected: '/steal' },
      ];

      testCases.forEach(({ input, expected }) => {
        const result = sanitizer.sanitizeReturnTo(input, FALLBACK);
        expect(result).toBe(expected);
      });
    });

    it('should reject paths starting with /api/', () => {
      const apiPaths = [
        '/api/users',
        '/api/auth/login',
        '/api/internal/endpoint',
      ];

      apiPaths.forEach(path => {
        const result = sanitizer.sanitizeReturnTo(path, FALLBACK);
        expect(result).toBe(FALLBACK);
      });
    });

    it('should reject paths starting with /_next/', () => {
      const nextPaths = [
        '/_next/static',
        '/_next/data',
        '/_next/image',
      ];

      nextPaths.forEach(path => {
        const result = sanitizer.sanitizeReturnTo(path, FALLBACK);
        expect(result).toBe(FALLBACK);
      });
    });

    it('should reject paths with file extensions', () => {
      const filePaths = [
        '/document.pdf',
        '/image.jpg',
        '/script.js',
        '/style.css',
        '/data.json',
        '/path/to/file.txt',
      ];

      filePaths.forEach(path => {
        const result = sanitizer.sanitizeReturnTo(path, FALLBACK);
        expect(result).toBe(FALLBACK);
      });
    });

    it('should reject relative paths without leading /', () => {
      const relativePaths = [
        'dashboard',
        'profile/settings',
        '../evil',
        './local',
      ];

      relativePaths.forEach(path => {
        const result = sanitizer.sanitizeReturnTo(path, FALLBACK);
        expect(result).toBe(FALLBACK);
      });
    });

    it('should handle complex valid paths', () => {
      const complexPaths = [
        '/leagues/abc-123/schedule',
        '/races/456/results',
        '/profile/liveries/upload',
        '/sponsor/leagues/def-456',
      ];

      complexPaths.forEach(path => {
        const result = sanitizer.sanitizeReturnTo(path, FALLBACK);
        expect(result).toBe(path);
      });
    });

    it('should handle absolute URLs with query parameters', () => {
      const result = sanitizer.sanitizeReturnTo(
        'https://example.com/dashboard?tab=settings',
        FALLBACK
      );
      expect(result).toBe('/dashboard?tab=settings');
    });

    it('should handle relative paths with query parameters', () => {
      const result = sanitizer.sanitizeReturnTo(
        '/profile?section=security',
        FALLBACK
      );
      expect(result).toBe('/profile?section=security');
    });

    it('should reject paths with multiple dots (potential file extensions)', () => {
      const paths = [
        '/path/file.tar.gz',
        '/api/v1/data.xml',
        '/download/file.backup',
      ];

      paths.forEach(path => {
        const result = sanitizer.sanitizeReturnTo(path, FALLBACK);
        expect(result).toBe(FALLBACK);
      });
    });

    it('should accept paths with dots that are not extensions', () => {
      const validPaths = [
        '/leagues/v1.0/dashboard', // version in path
        '/user/john.doe', // username with dot
      ];

      validPaths.forEach(path => {
        const result = sanitizer.sanitizeReturnTo(path, FALLBACK);
        expect(result).toBe(path);
      });
    });
  });
});
