/**
 * Form Validation Utilities
 * Utilities for applying API validation errors to form fields
 */

import type { ApiError } from '@/schemas/apiSchemas';
import { getValidationErrors, getErrorCategory } from './apiErrorHandler';
import type { UseFormSetError, Path } from 'react-hook-form';

/**
 * Applies API validation errors to react-hook-form fields
 * @param error - The API error containing validation details
 * @param setError - react-hook-form's setError function
 * @param fieldNameMap - Optional mapping from API field names to form field names
 * @returns true if validation errors were applied, false otherwise
 */
export function applyApiValidationErrors<T extends Record<string, any>>(
  error: ApiError | Error | unknown,
  setError: UseFormSetError<T>,
  fieldNameMap?: Record<string, keyof T>,
): boolean {
  // Check if this is a validation error
  const apiError =
    error && typeof error === 'object' && 'message' in error
      ? (error as ApiError)
      : null;

  if (!apiError) {
    return false;
  }

  const category = getErrorCategory(apiError);
  if (category !== 'validation') {
    return false;
  }

  // Extract validation errors from error.details
  const validationErrors = getValidationErrors(apiError);

  if (Object.keys(validationErrors).length === 0) {
    return false;
  }

  // Apply errors to form fields
  let appliedCount = 0;
  for (const [apiFieldName, message] of Object.entries(validationErrors)) {
    // Map API field name to form field name if mapping provided
    const formFieldName = (fieldNameMap?.[apiFieldName] ||
      apiFieldName) as Path<T>;

    // Set error on the form field
    setError(formFieldName, {
      type: 'server',
      message: message,
    });

    appliedCount++;
  }

  return appliedCount > 0;
}

/**
 * Gets validation error for a specific field from an API error
 * @param error - The API error
 * @param fieldName - The field name to get error for
 * @param fieldNameMap - Optional mapping from API field names to form field names
 * @returns Error message for the field, or undefined if no error
 */
export function getFieldValidationError(
  error: ApiError | Error | unknown,
  fieldName: string,
  fieldNameMap?: Record<string, string>,
): string | undefined {
  const apiError =
    error && typeof error === 'object' && 'message' in error
      ? (error as ApiError)
      : null;

  if (!apiError) {
    return undefined;
  }

  const category = getErrorCategory(apiError);
  if (category !== 'validation') {
    return undefined;
  }

  const validationErrors = getValidationErrors(apiError);

  // Check direct field name
  if (validationErrors[fieldName]) {
    return validationErrors[fieldName];
  }

  // Check mapped field name
  if (fieldNameMap) {
    for (const [apiFieldName, formFieldName] of Object.entries(fieldNameMap)) {
      if (formFieldName === fieldName && validationErrors[apiFieldName]) {
        return validationErrors[apiFieldName];
      }
    }
  }

  return undefined;
}

/**
 * Checks if an error is a validation error
 * @param error - The error to check
 * @returns true if the error is a validation error
 */
export function isValidationError(error: ApiError | Error | unknown): boolean {
  const apiError =
    error && typeof error === 'object' && 'message' in error
      ? (error as ApiError)
      : null;

  if (!apiError) {
    return false;
  }

  return getErrorCategory(apiError) === 'validation';
}
