/**
 * Copyright IBM Corp. 2024, 2025
 */

import { ZodError, z } from 'zod';
import { transformZodErrors } from '../../src/helpers/zod-error-formatter.helper.js';

describe('zod-error-formatter.helper', () => {
  describe('transformZodErrors', () => {
    it('should return the original error if it is not a ZodError', () => {
      // Arrange
      const originalError = new Error('Original error');

      // Act
      const result = transformZodErrors(originalError);

      // Assert
      expect(result).toBe(originalError);
    });

    it('should transform a ZodError with a single issue into a formatted Error', () => {
      // Arrange
      const schema = z.object({
        name: z.string(),
      });
      let zodError: ZodError;

      try {
        schema.parse({ name: 123 });
      } catch (error) {
        zodError = error as ZodError;

        // Act
        const result = transformZodErrors(zodError);

        // Assert
        expect(result).toBeInstanceOf(Error);
        expect(result.message).toContain(
          `Validation error at name: Invalid input: expected string, received number`,
        );
      }
    });

    it('should transform a ZodError with multiple issues into a formatted Error', () => {
      // Arrange
      const schema = z.object({
        name: z.string(),
        age: z.number().positive(),
      });
      let zodError: ZodError;

      try {
        schema.parse({ name: 123, age: -5 });
      } catch (error) {
        zodError = error as ZodError;

        // Act
        const result = transformZodErrors(zodError);

        // Assert
        expect(result).toBeInstanceOf(Error);
        expect(result.message).toContain(`Validation error at name:`);
        expect(result.message).toContain(`Validation error at age:`);
      }
    });

    it('should handle nested object validation errors', () => {
      // Arrange
      const schema = z.object({
        user: z.object({
          profile: z.object({
            email: z.string().email(),
          }),
        }),
      });
      let zodError: ZodError;

      try {
        schema.parse({ user: { profile: { email: 'not-an-email' } } });
      } catch (error) {
        zodError = error as ZodError;

        // Act
        const result = transformZodErrors(zodError);

        // Assert
        expect(result).toBeInstanceOf(Error);
        expect(result.message).toContain(
          `Validation error at user.profile.email:`,
        );
        expect(result.message).toContain('Invalid email');
      }
    });

    it('should handle array validation errors with proper indexing', () => {
      // Arrange
      const schema = z.object({
        items: z.array(z.string()),
      });
      let zodError: ZodError;

      try {
        schema.parse({ items: ['valid', 123, 'also-valid'] });
      } catch (error) {
        zodError = error as ZodError;

        // Act
        const result = transformZodErrors(zodError);

        // Assert
        expect(result).toBeInstanceOf(Error);
        expect(result.message).toContain(
          `Validation error at items.[1]: Invalid input: expected string, received number`,
        );
      }
    });

    it('should handle errors without paths', () => {
      // Arrange
      // Create a mock ZodError with an issue that has no path
      const mockIssue = {
        message: 'Generic validation error',
        path: [],
      };
      const mockZodError = new ZodError([mockIssue as any]);

      // Act
      const result = transformZodErrors(mockZodError);

      // Assert
      expect(result).toBeInstanceOf(Error);
      expect(result.message).toBe('Generic validation error');
    });

    it('should handle empty issues array', () => {
      // Arrange
      // Create a mock ZodError with no issues
      const mockZodError = new ZodError([]);

      // Act
      const result = transformZodErrors(mockZodError);

      // Assert
      expect(result).toBeInstanceOf(Error);
      expect(result.message).toBe('Validation error occurred');
    });
  });
});
