/**
 * Utility Functions Tests
 */

import {
  formatPercentage,
  formatProgress,
  calculateTrend,
  isValidPostcode,
  debounce,
} from '@/lib/utils';

describe('formatPercentage', () => {
  it('formats percentages correctly', () => {
    expect(formatPercentage(75.5)).toBe('75.5%');
    expect(formatPercentage(100)).toBe('100.0%');
    expect(formatPercentage(0)).toBe('0.0%');
  });

  it('handles null values', () => {
    expect(formatPercentage(null)).toBe('-');
  });
});

describe('formatProgress', () => {
  it('formats progress scores correctly', () => {
    expect(formatProgress(2.5)).toBe('+2.5');
    expect(formatProgress(-1.3)).toBe('-1.3');
    expect(formatProgress(0)).toBe('0.0');
  });

  it('handles null values', () => {
    expect(formatProgress(null)).toBe('-');
  });
});

describe('calculateTrend', () => {
  it('calculates upward trend', () => {
    expect(calculateTrend(75, 70)).toBe('up');
  });

  it('calculates downward trend', () => {
    expect(calculateTrend(70, 75)).toBe('down');
  });

  it('calculates same trend', () => {
    expect(calculateTrend(75, 75)).toBe('same');
  });

  it('handles null previous value', () => {
    expect(calculateTrend(75, null)).toBe('same');
  });

  it('handles null current value', () => {
    expect(calculateTrend(null, 75)).toBe('same');
  });
});

describe('isValidPostcode', () => {
  it('validates correct UK postcodes', () => {
    expect(isValidPostcode('SW1A 1AA')).toBe(true);
    expect(isValidPostcode('M1 1AE')).toBe(true);
    expect(isValidPostcode('B33 8TH')).toBe(true);
  });

  it('rejects invalid postcodes', () => {
    expect(isValidPostcode('INVALID')).toBe(false);
    expect(isValidPostcode('12345')).toBe(false);
    expect(isValidPostcode('')).toBe(false);
  });
});

describe('debounce', () => {
  jest.useFakeTimers();

  it('delays function execution', () => {
    const mockFn = jest.fn();
    const debouncedFn = debounce(mockFn, 300);

    debouncedFn('test');
    expect(mockFn).not.toHaveBeenCalled();

    jest.advanceTimersByTime(300);
    expect(mockFn).toHaveBeenCalledWith('test');
    expect(mockFn).toHaveBeenCalledTimes(1);
  });

  it('cancels previous calls', () => {
    const mockFn = jest.fn();
    const debouncedFn = debounce(mockFn, 300);

    debouncedFn('first');
    jest.advanceTimersByTime(150);
    debouncedFn('second');
    jest.advanceTimersByTime(150);
    debouncedFn('third');
    jest.advanceTimersByTime(300);

    expect(mockFn).toHaveBeenCalledWith('third');
    expect(mockFn).toHaveBeenCalledTimes(1);
  });

  jest.useRealTimers();
});
