/**
 * Tests for ID Normalization
 * FE-TYPE-001: Test ID normalization utilities
 */

import { describe, it, expect } from 'vitest';
import {
  normalizeId,
  normalizeIdRequired,
  normalizeIds,
  normalizeObjectIds,
  normalizeArrayIds,
  isValidId,
  isValidStringId,
} from './idNormalization';

describe('idNormalization', () => {
  describe('normalizeId', () => {
    it('should return string ID as-is', () => {
      expect(normalizeId('abc-123')).toBe('abc-123');
      expect(normalizeId('123e4567-e89b-12d3-a456-426614174000')).toBe(
        '123e4567-e89b-12d3-a456-426614174000',
      );
    });

    it('should convert number ID to string', () => {
      expect(normalizeId(123)).toBe('123');
      expect(normalizeId(0)).toBe('0');
    });

    it('should return undefined for null or undefined', () => {
      expect(normalizeId(null)).toBeUndefined();
      expect(normalizeId(undefined)).toBeUndefined();
    });
  });

  describe('normalizeIdRequired', () => {
    it('should return string ID as-is', () => {
      expect(normalizeIdRequired('abc-123')).toBe('abc-123');
    });

    it('should convert number ID to string', () => {
      expect(normalizeIdRequired(123)).toBe('123');
    });

    it('should throw error for null or undefined', () => {
      expect(() => normalizeIdRequired(null)).toThrow('ID is required');
      expect(() => normalizeIdRequired(undefined)).toThrow('ID is required');
    });
  });

  describe('normalizeIds', () => {
    it('should normalize array of IDs', () => {
      expect(normalizeIds([1, 2, 'abc'])).toEqual(['1', '2', 'abc']);
    });

    it('should filter out null and undefined', () => {
      expect(normalizeIds([1, null, 'abc', undefined])).toEqual(['1', 'abc']);
    });
  });

  describe('normalizeObjectIds', () => {
    it('should normalize ID fields in object', () => {
      const obj = {
        id: 123,
        user_id: 456,
        name: 'test',
      };

      const normalized = normalizeObjectIds(obj);

      expect(normalized.id).toBe('123');
      expect(normalized.user_id).toBe('456');
      expect(normalized.name).toBe('test');
    });

    it('should normalize nested objects', () => {
      const obj = {
        id: 123,
        user: {
          id: 456,
          name: 'John',
        },
      };

      const normalized = normalizeObjectIds(obj);

      expect(normalized.id).toBe('123');
      expect(normalized.user.id).toBe('456');
      expect(normalized.user.name).toBe('John');
    });

    it('should normalize arrays of objects', () => {
      const obj = {
        id: 123,
        items: [
          { id: 1, name: 'item1' },
          { id: 2, name: 'item2' },
        ],
      };

      const normalized = normalizeObjectIds(obj);

      expect(normalized.id).toBe('123');
      expect(normalized.items[0].id).toBe('1');
      expect(normalized.items[1].id).toBe('2');
    });

    it('should handle string IDs without conversion', () => {
      const obj = {
        id: 'abc-123',
        user_id: 'def-456',
      };

      const normalized = normalizeObjectIds(obj);

      expect(normalized.id).toBe('abc-123');
      expect(normalized.user_id).toBe('def-456');
    });

    it('should normalize custom ID fields', () => {
      const obj = {
        track_id: 123,
        playlist_id: 456,
      };

      const normalized = normalizeObjectIds(obj, ['track_id', 'playlist_id']);

      expect(normalized.track_id).toBe('123');
      expect(normalized.playlist_id).toBe('456');
    });
  });

  describe('normalizeArrayIds', () => {
    it('should normalize IDs in array of objects', () => {
      const items = [
        { id: 1, name: 'item1' },
        { id: 2, name: 'item2' },
      ];

      const normalized = normalizeArrayIds(items);

      expect(normalized[0].id).toBe('1');
      expect(normalized[1].id).toBe('2');
    });
  });

  describe('isValidId', () => {
    it('should return true for string IDs', () => {
      expect(isValidId('abc-123')).toBe(true);
    });

    it('should return true for number IDs', () => {
      expect(isValidId(123)).toBe(true);
    });

    it('should return false for invalid IDs', () => {
      expect(isValidId(null)).toBe(false);
      expect(isValidId(undefined)).toBe(false);
      expect(isValidId({})).toBe(false);
    });
  });

  describe('isValidStringId', () => {
    it('should return true for non-empty string IDs', () => {
      expect(isValidStringId('abc-123')).toBe(true);
    });

    it('should return false for empty strings', () => {
      expect(isValidStringId('')).toBe(false);
    });

    it('should return false for non-string values', () => {
      expect(isValidStringId(123)).toBe(false);
      expect(isValidStringId(null)).toBe(false);
    });
  });
});
