/**
 * useFormValidation Hook
 * Action 5.2.1.3: Hook for pre-validation of form data
 */

import { useState, useCallback, useRef, useEffect } from 'react';
import { apiClient } from '@/services/api/client';
import { parseApiError } from '@/utils/apiErrorHandler';
import { logger } from '@/utils/logger';
import type { ApiError } from '@/schemas/apiSchemas';

/**
 * Validation error from backend
 */
export interface ValidationError {
  field: string;
  message: string;
  value?: string;
}

/**
 * Validation response from backend
 */
interface ValidateResponse {
  valid: boolean;
  errors?: ValidationError[];
  message?: string;
}

/**
 * Options for useFormValidation hook
 */
export interface UseFormValidationOptions {
  /** Validation type (e.g., "RegisterRequest", "LoginRequest") */
  type: string;
  /** Whether to validate automatically on data change */
  autoValidate?: boolean;
  /** Debounce delay in milliseconds (0 = no debounce) */
  debounceMs?: number;
}

/**
 * Return type for useFormValidation hook
 */
export interface UseFormValidationReturn {
  /** Whether validation is in progress */
  isValidating: boolean;
  /** Validation errors from backend */
  errors: ValidationError[];
  /** Whether the current data is valid */
  isValid: boolean | null;
  /** Last validation error (if any) */
  error: ApiError | null;
  /** Validate the provided data */
  validate: (data: unknown) => Promise<boolean>;
  /** Clear validation state */
  clear: () => void;
}

/**
 * Hook for pre-validating form data against backend validation rules
 *
 * @param options - Validation options
 * @returns Validation state and functions
 *
 * @example
 * ```tsx
 * const { isValidating, errors, validate, isValid } = useFormValidation({
 *   type: 'RegisterRequest',
 * });
 *
 * const handleBlur = async () => {
 *   await validate(formData);
 * };
 * ```
 */
export function useFormValidation(
  options: UseFormValidationOptions,
): UseFormValidationReturn {
  const { type, debounceMs = 300 } = options;
  const [isValidating, setIsValidating] = useState(false);
  const [errors, setErrors] = useState<ValidationError[]>([]);
  const [isValid, setIsValid] = useState<boolean | null>(null);
  const [error, setError] = useState<ApiError | null>(null);
  const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);
  const validationIdRef = useRef<number>(0);

  // Internal validation function (not debounced)
  const performValidation = useCallback(
    async (data: unknown, validationId: number): Promise<boolean> => {
      if (!type) {
        logger.warn('[useFormValidation] Validation type is required');
        return false;
      }

      setIsValidating(true);
      setError(null);

      try {
        const response = await apiClient.post<ValidateResponse>(
          '/api/v1/validate',
          {
            type,
            data,
          },
        );

        // Only update state if this is still the latest validation
        if (validationId !== validationIdRef.current) {
          return false; // Validation was superseded
        }

        const validationResult = response.data;

        // Handle both wrapped and direct response formats
        const result =
          typeof validationResult === 'object' && 'data' in validationResult
            ? (validationResult as { data: ValidateResponse }).data
            : validationResult;

        if (result.valid) {
          setErrors([]);
          setIsValid(true);
          return true;
        } else {
          setErrors(result.errors || []);
          setIsValid(false);
          return false;
        }
      } catch (err) {
        // Only update state if this is still the latest validation
        if (validationId !== validationIdRef.current) {
          return false; // Validation was superseded
        }

        const apiError = parseApiError(err);
        setError(apiError);
        setErrors([]);
        setIsValid(false);
        logger.error('[useFormValidation] Validation request failed', {
          error: apiError.message,
          type,
        });
        return false;
      } finally {
        // Only clear validating state if this is still the latest validation
        if (validationId === validationIdRef.current) {
          setIsValidating(false);
        }
      }
    },
    [type],
  );

  // Debounced validate function
  const validate = useCallback(
    async (data: unknown): Promise<boolean> => {
      // If debounce is disabled (0 or negative), validate immediately
      if (debounceMs <= 0) {
        validationIdRef.current += 1;
        return performValidation(data, validationIdRef.current);
      }

      // Clear existing timer
      if (debounceTimerRef.current) {
        clearTimeout(debounceTimerRef.current);
      }

      // Increment validation ID to cancel previous validation
      validationIdRef.current += 1;
      const currentValidationId = validationIdRef.current;

      // Return a promise that resolves when validation completes
      return new Promise<boolean>((resolve) => {
        debounceTimerRef.current = setTimeout(async () => {
          // Only validate if this is still the latest validation request
          if (currentValidationId === validationIdRef.current) {
            const result = await performValidation(data, currentValidationId);
            resolve(result);
          } else {
            // Validation was superseded, resolve with false
            resolve(false);
          }
        }, debounceMs);
      });
    },
    [debounceMs, performValidation],
  );

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      if (debounceTimerRef.current) {
        clearTimeout(debounceTimerRef.current);
      }
    };
  }, []);

  const clear = useCallback(() => {
    setErrors([]);
    setIsValid(null);
    setError(null);
    setIsValidating(false);
  }, []);

  return {
    isValidating,
    errors,
    isValid,
    error,
    validate,
    clear,
  };
}
