import { ZodError, z } from 'zod';
import { extractZodErrorMessage } from './zod-error.helper';

describe('ZodErrorHelper', () => {
  describe('extractZodErrorMessage', () => {
    it('should return default message for empty issues', () => {
      const error = new ZodError([]);
      const result = extractZodErrorMessage(error);

      expect(result).toBe('Unbekannter Validierungsfehler aufgetreten.');
    });

    it('should format single invalid_type error', () => {
      const schema = z.string();

      try {
        schema.parse(123);
      } catch (error) {
        if (error instanceof ZodError) {
          const result = extractZodErrorMessage(error);
          expect(result).toBe('Erwartet: Text, erhalten: Zahl');
        }
      }
    });

    it('should format invalid_string error for email validation', () => {
      const schema = z.object({
        email: z.string().email(),
      });

      try {
        schema.parse({ email: 'invalid-email' });
      } catch (error) {
        if (error instanceof ZodError) {
          const result = extractZodErrorMessage(error);
          expect(result).toBe('email: Ungültige E-Mail-Adresse');
        }
      }
    });

    it('should format too_small error for strings', () => {
      const schema = z.object({
        name: z.string().min(5),
      });

      try {
        schema.parse({ name: 'ab' });
      } catch (error) {
        if (error instanceof ZodError) {
          const result = extractZodErrorMessage(error);
          expect(result).toBe('name: Text muss mindestens 5 Zeichen lang sein');
        }
      }
    });

    it('should format multiple errors with bullet points', () => {
      const schema = z.object({
        name: z.string(),
        age: z.number(),
      });

      try {
        schema.parse({ name: 123, age: 'not-a-number' });
      } catch (error) {
        if (error instanceof ZodError) {
          const result = extractZodErrorMessage(error);

          expect(result).toContain('Es sind 2 Validierungsfehler aufgetreten:');
          expect(result).toContain('• name: Erwartet: Text, erhalten: Zahl');
          expect(result).toContain('• age: Erwartet: Zahl, erhalten: Text');
        }
      }
    });

    it('should format nested path correctly', () => {
      const schema = z.object({
        user: z.object({
          profile: z.object({
            email: z.string().email(),
          }),
        }),
      });

      try {
        schema.parse({
          user: {
            profile: {
              email: 'invalid-email',
            },
          },
        });
      } catch (error) {
        if (error instanceof ZodError) {
          const result = extractZodErrorMessage(error);
          expect(result).toBe('user → profile → email: Ungültige E-Mail-Adresse');
        }
      }
    });

    it('should handle array indices in paths', () => {
      const schema = z.array(z.string());

      try {
        schema.parse(['valid', 123, 'also-valid']);
      } catch (error) {
        if (error instanceof ZodError) {
          const result = extractZodErrorMessage(error);
          expect(result).toBe('[1]: Erwartet: Text, erhalten: Zahl');
        }
      }
    });

    it('should handle custom error messages', () => {
      const schema = z.string().refine((val) => val === 'specific', {
        message: 'Must be exactly "specific"',
      });

      try {
        schema.parse('wrong');
      } catch (error) {
        if (error instanceof ZodError) {
          const result = extractZodErrorMessage(error);
          expect(result).toBe('Must be exactly "specific"');
        }
      }
    });
  });
});