import { useState, useCallback } from 'react';
import { z } from 'zod';
import i18n from "@/lib/i18n";

interface UseFormOptions<T> {
  initialValues: T;
  validationSchema?: z.ZodSchema<T>;
  onSubmit: (values: T) => Promise<void>;
}

interface ValidationErrors {
  [key: string]: string;
}

export function useForm<T extends Record<string, unknown>>({
  initialValues,
  validationSchema,
  onSubmit,
}: UseFormOptions<T>) {
  const [values, setValues] = useState<T>(initialValues);
  const [errors, setErrors] = useState<ValidationErrors>({});
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [submitError, setSubmitError] = useState<string | null>(null);
  const [submitSuccess, setSubmitSuccess] = useState<string | null>(null);

  const setValue = useCallback(
    (name: keyof T, value: unknown) => {
      setValues((prev) => ({ ...prev, [name]: value }));
      if (errors[name as string]) {
        setErrors((prev) => ({ ...prev, [name as string]: '' }));
      }
    },
    [errors],
  );

  const setFieldError = useCallback((name: keyof T, error: string) => {
    setErrors((prev) => ({ ...prev, [name as string]: error }));
  }, []);

  const clearFieldError = useCallback((name: keyof T) => {
    setErrors((prev) => ({ ...prev, [name as string]: '' }));
  }, []);

  const clearAllErrors = useCallback(() => {
    setErrors({});
  }, []);

  const validate = useCallback((): boolean => {
    if (!validationSchema) return true;

    try {
      validationSchema.parse(values);
      setErrors({});
      return true;
    } catch (error) {
      const validationErrors: ValidationErrors = {};

      if (error && typeof error === 'object' && 'errors' in error) {
        const zodError = error as { errors: Array<{ path: string[]; message: string }> };
        zodError.errors.forEach((err) => {
          const field = err.path[0];
          validationErrors[field] = err.message;
        });
      }

      setErrors(validationErrors);
      return false;
    }
  }, [values, validationSchema]);

  const handleSubmit = useCallback(
    async (e?: React.FormEvent) => {
      if (e) {
        e.preventDefault();
      }

      setSubmitError(null);
      setSubmitSuccess(null);

      if (!validate()) {
        return;
      }

      setIsSubmitting(true);

      try {
        await onSubmit(values);
        setSubmitSuccess(i18n.t('hooks.useForm.text_1'));
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : i18n.t('hooks.useForm.text_2');
        setSubmitError(errorMessage);
        throw error;
      } finally {
        setIsSubmitting(false);
      }
    },
    [values, validate, onSubmit],
  );

  const reset = useCallback(() => {
    setValues(initialValues);
    setErrors({});
    setSubmitError(null);
    setSubmitSuccess(null);
  }, [initialValues]);

  const handleInputChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
      const { name, value, type } = e.target;

      let processedValue: unknown = value;

      if (type === 'number') {
        processedValue = value === '' ? '' : Number(value);
      } else if (type === 'checkbox') {
        processedValue = (e.target as HTMLInputElement).checked;
      }

      setValue(name as keyof T, processedValue);
    },
    [setValue],
  );

  const getFieldProps = useCallback(
    (name: keyof T) => ({
      name: name as string,
      value: values[name],
      onChange: handleInputChange,
      error: errors[name as string],
    }),
    [values, errors, handleInputChange],
  );

  return {
    values,
    errors,
    isSubmitting,
    submitError,
    submitSuccess,
    setValue,
    setFieldError,
    clearFieldError,
    clearAllErrors,
    validate,
    handleSubmit,
    reset,
    handleInputChange,
    getFieldProps,
    setSubmitError,
    setSubmitSuccess,
  };
}