/**
 * Tests for getFirstValidationError utility
 */

import {
  getFirstValidationError,
  getAllValidationErrors,
} from '@/lib/forms/utils/getFirstValidationError';
import type { FieldErrors } from 'react-hook-form';

describe('getFirstValidationError', () => {
  it('returns null for empty errors object', () => {
    const result = getFirstValidationError({});
    expect(result).toBeNull();
  });

  it('extracts direct error message', () => {
    const errors: FieldErrors = {
      name: { message: 'Name is required', type: 'required' },
    };
    const result = getFirstValidationError(errors);
    expect(result).toEqual({ field: 'name', message: 'Name is required' });
  });

  it('extracts nested error message', () => {
    const errors: FieldErrors = {
      model_params: {
        temperature: { message: 'Temperature must be a number', type: 'type' },
      },
    };
    const result = getFirstValidationError(errors);
    expect(result).toEqual({
      field: 'model_params.temperature',
      message: 'Temperature must be a number',
    });
  });

  it('returns first error when multiple fields have errors', () => {
    const errors: FieldErrors = {
      name: { message: 'Name is required', type: 'required' },
      slug: { message: 'Slug is required', type: 'required' },
    };
    const result = getFirstValidationError(errors);
    // Object.keys order is insertion order, so 'name' comes first
    expect(result?.field).toBe('name');
    expect(result?.message).toBe('Name is required');
  });

  it('handles deeply nested errors', () => {
    const errors: FieldErrors = {
      config: {
        nested: {
          deep: { message: 'Deep error', type: 'validation' },
        },
      },
    };
    const result = getFirstValidationError(errors);
    expect(result).toEqual({ field: 'config.nested.deep', message: 'Deep error' });
  });

  it('skips null error entries', () => {
    const errors: FieldErrors = {
      name: null as unknown as undefined,
      slug: { message: 'Slug is required', type: 'required' },
    };
    const result = getFirstValidationError(errors);
    expect(result).toEqual({ field: 'slug', message: 'Slug is required' });
  });

  it('handles error object with ref but no message', () => {
    // react-hook-form errors may have 'ref' property but no 'message'
    // We cast to FieldErrors to simulate edge cases
    const errors = {
      name: { type: 'required', ref: { current: null } },
      slug: { message: 'Slug is required', type: 'required' },
    } as unknown as FieldErrors;
    const result = getFirstValidationError(errors);
    // Should skip name (no message) and find slug
    expect(result).toEqual({ field: 'slug', message: 'Slug is required' });
  });
});

describe('getAllValidationErrors', () => {
  it('returns empty array for empty errors object', () => {
    const result = getAllValidationErrors({});
    expect(result).toEqual([]);
  });

  it('returns all errors as flat array', () => {
    const errors: FieldErrors = {
      name: { message: 'Name is required', type: 'required' },
      slug: { message: 'Slug is required', type: 'required' },
    };
    const result = getAllValidationErrors(errors);
    expect(result).toHaveLength(2);
    expect(result).toContainEqual({ field: 'name', message: 'Name is required' });
    expect(result).toContainEqual({ field: 'slug', message: 'Slug is required' });
  });

  it('flattens nested errors', () => {
    const errors: FieldErrors = {
      model_params: {
        temperature: { message: 'Invalid temperature', type: 'type' },
        max_tokens: { message: 'Invalid max tokens', type: 'type' },
      },
    };
    const result = getAllValidationErrors(errors);
    expect(result).toHaveLength(2);
    expect(result).toContainEqual({
      field: 'model_params.temperature',
      message: 'Invalid temperature',
    });
    expect(result).toContainEqual({
      field: 'model_params.max_tokens',
      message: 'Invalid max tokens',
    });
  });

  it('combines direct and nested errors', () => {
    const errors: FieldErrors = {
      name: { message: 'Name is required', type: 'required' },
      model_params: {
        temperature: { message: 'Invalid temperature', type: 'type' },
      },
    };
    const result = getAllValidationErrors(errors);
    expect(result).toHaveLength(2);
    expect(result).toContainEqual({ field: 'name', message: 'Name is required' });
    expect(result).toContainEqual({
      field: 'model_params.temperature',
      message: 'Invalid temperature',
    });
  });
});
