// Import necessary modules and components
import { FieldErrors, Resolver, SubmitHandler, useForm } from "react-hook-form";
import { CategoryDatasourceProd } from "../../data/datasource/api/category_datasource";
import { CategoryRepositoryProd } from "../../data/repository/category_repository";
import {
  Category,
  CategoryFormValues,
} from "../../data/datasource/api/entities/category";
import axios, { AxiosError } from "axios";
import { toast } from "react-toastify";
import { useEffect, useState } from "react";
import { showErrorAxios } from "../../core/utils/Messages";

// Initialize data source and repository for categories
const categoryDatasource = new CategoryDatasourceProd();
const categoryRepository = new CategoryRepositoryProd(categoryDatasource);

// Define resolver for form validation
const resolver: Resolver<CategoryFormValues> = async (data) => {
  const errors: FieldErrors<CategoryFormValues> = {};

  // Validate Spanish name
  if (!data.nameES) {
    errors.nameES = {
      type: "required",
      message: "El nombre en español de la categoría es requerido",
    };
  } else if (data.nameES.length > 255) {
    errors.nameES = {
      type: "maxLength",
      message: "El tamaño no debe sobrepasar los 255 caracteres",
    };
  }

  // Validate English name
  if (!data.nameEN) {
    errors.nameEN = {
      type: "required",
      message: "El nombre en inglés de la categoría es requerido",
    };
  } else if (data.nameEN.length > 255) {
    errors.nameEN = {
      type: "maxLength",
      message: "El tamaño no debe sobrepasar los 255 caracteres",
    };
  }

  return {
    values: Object.keys(errors).length > 0 ? {} : data,
    errors: errors,
  };
};

// Custom hook for category management
export const useCategory = (
  forceRenderList?: () => void,
  handleClickToClose?: () => void
) => {
  // Initialize form handling and state management
  const {
    register,
    handleSubmit,
    setValue,
    formState: { errors },
    clearErrors,
    resetField,
  } = useForm<CategoryFormValues>({ resolver });
  const [pending, setPending] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [categoriesList, setCategoriesList] = useState<Category[]>([]);

  // Handle form submission
  const onSubmit: SubmitHandler<CategoryFormValues> = (
    data: CategoryFormValues
  ) => {
    const fetch = async () => {
      try {
        await categoryRepository.registerCategory(data).then(() => {
          if (forceRenderList && handleClickToClose) {
            updateCategoriesList();
            forceRenderList();
            handleClickToClose();
          }
        });
      } catch (error: any) {
        let errorMessage: string = "Ha ocurrido un error";
        if (axios.isAxiosError(error)) {
          error as AxiosError;
          switch (error.code) {
            case axios.AxiosError.ERR_BAD_REQUEST:
              errorMessage = "Acceso no autorizado";
              break;
            case axios.AxiosError.ERR_NETWORK:
              errorMessage = "Conexión con el servidor fallida";
              break;
          }
        }
        throw new Error(errorMessage);
      }
    };
    toast.promise(fetch(), {
      pending: "Subiendo datos...",
      success: "Los datos se han subido correctamente",
      error: {
        render({ data }) {
          return (data as Error).message;
        },
      },
    });
  };

  // Update the list of categories
  const updateCategoriesList = async () => {
    setPending(true);
    try {
      const categories = await categoryRepository.getCategories();
      setCategoriesList(categories);
      setPending(false);
    } catch (error: any) {
      if (axios.isAxiosError(error)) {
        error as AxiosError;
        showErrorAxios(error);
      }
      setPending(false);
    }
  };

  // Fetch categories on component mount
  useEffect(() => {
    setIsLoading(true);
    updateCategoriesList();
    setIsLoading(false);
  }, []);

  // Delete a category
  const deleteCategory = async (category: Category) => {
    await categoryRepository.deleteCategory(category);
    await updateCategoriesList();
  };

  return {
    register,
    handleSubmit,
    errors,
    onSubmit,
    setValue,
    clearErrors,
    resetField,
    updateCategoriesList,
    categoriesList,
    pending,
    deleteCategory,
    isLoading,
  };
};
