// Import necessary modules and components
import { FieldErrors, Resolver, SubmitHandler, useForm } from "react-hook-form";
import { AdminDatasourceProd } from "../../data/datasource/api/admin_datasource";
import { AdminRepositoryProd } from "../../data/repository/admin_repository";
import {
  Admin,
  AdminFormValues,
} from "../../data/datasource/api/entities/admin_form_values";
import { toast } from "react-toastify";
import axios, { AxiosError } from "axios";
import { useState } from "react";
import { showErrorAxios } from "../../core/utils/Messages";

// Initialize data source and repository for admin
const adminDatasource = new AdminDatasourceProd();
const adminRepository = new AdminRepositoryProd(adminDatasource);

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

  // Validate name
  if (!data.name) {
    errors.name = {
      type: "required",
      message: "El nombre del administrador es requerido",
    };
  } else if (data.name.length > 255) {
    errors.name = {
      type: "maxLength",
      message: "El tamaño no debe sobrepasar los 255 caracteres",
    };
  }

  // Validate last name
  if (!data.lastName) {
    errors.lastName = {
      type: "required",
      message: "El apellido del administrador es requerido",
    };
  } else if (data.lastName.length > 255) {
    errors.lastName = {
      type: "maxLength",
      message: "El tamaño no debe sobrepasar los 255 caracteres",
    };
  }

  // Validate email
  if (!data.email) {
    errors.email = {
      type: "required",
      message: "El correo electronico es requerido",
    };
  } else {
    const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    if (!emailPattern.test(data.email)) {
      errors.email = {
        type: "validate",
        message: "El correo electronico no es válido",
      };
    }

    if (data.email.length > 255) {
      errors.email = {
        type: "maxLength",
        message: "El tamaño no debe sobrepasar los 255 caracteres",
      };
    }
  }

  // Validate password
  if (!data.password) {
    errors.password = {
      type: "required",
      message: "La contraseña es requerida",
    };
  } else if (data.confirmPassword !== data.password) {
    errors.confirmPassword = {
      type: "validate",
      message: "Las contraseñas deben coincidir",
    };
  }

  // Validate password confirmation
  if (!data.confirmPassword) {
    errors.confirmPassword = {
      type: "required",
      message: "La contraseña es requerida",
    };
  }

  // Validate town admin selection
  if (!data.townAdmin) {
    errors.townAdmin = {
      type: "required",
      message: "Elija el pueblo al que va a representar",
    };
  }

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

// Custom hook for managing admin functionalities
export const useAdmin = (
  forceRenderList?: () => void,
  handleClickToClose?: () => void
) => {
  // Initialize form handling and state management
  const {
    register,
    handleSubmit,
    formState: { errors },
    setError,
  } = useForm<AdminFormValues>({ resolver });
  const [adminList, setAdminList] = useState<Admin[]>([]);

  // Handle form submission
  const onSubmit: SubmitHandler<AdminFormValues> = (data: AdminFormValues) => {
    const fetch = async () => {
      try {
        await adminRepository.registerAdmin(data);
        if (forceRenderList && handleClickToClose) {
          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";
              setError("email", {
                type: "validate",
                message: "El email ya existe",
              });
              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;
        },
      },
    });
  };

  // Fetch admin information
  const getAdminInfo = async (): Promise<Admin | null> => {
    const token = localStorage.getItem("token");
    if (token) {
      try {
        const actualAdmin = await adminRepository.getAdminInfo(token);
        return actualAdmin;
      } catch (error: any) {
        if (axios.isAxiosError(error)) {
          error as AxiosError;
          showErrorAxios(error);
        }
      }
      return null;
    }
    return null;
  };

  // Fetch admin list by town
  const getAdminListByTown = async (idTown: number) => {
    try {
      const adminList = await adminRepository.getAdminsByTown(idTown);
      setAdminList(adminList);
    } catch (error: any) {
      if (axios.isAxiosError(error)) {
        error as AxiosError;
        showErrorAxios(error);
      }
    }
  };

  return {
    register,
    handleSubmit,
    errors,
    onSubmit,
    getAdminInfo,
    adminList,
    getAdminListByTown,
  };
};
