// Import necessary modules and hooks from libraries
import { FieldErrors, Resolver, SubmitHandler, useForm } from "react-hook-form";
import { Dispatch, SetStateAction, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import axios, { AxiosError } from "axios";
import { useAuth } from "../../core/context/auth_context";
import { LoginFormValues } from "../../data/datasource/api/entities/login_form_values";
import { LoginDatasourceImpl } from "../../data/datasource/api/login_datasource";
import { LoginRepositoryImpl } from "../../data/repository/login_repository";

// Initialize the login datasource and repository
const loginDatasource = new LoginDatasourceImpl();
const loginRepository = new LoginRepositoryImpl(loginDatasource);

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

  // Validate email field
  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",
      };
    }
  }

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

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

// Custom hook for handling login logic
export const useLogin = (setIsLoading: Dispatch<SetStateAction<boolean>>) => {
  const { login, user } = useAuth();
  const navigate = useNavigate();
  const {
    register,
    handleSubmit,
    setError,
    formState: { errors },
    clearErrors,
  } = useForm<LoginFormValues>({ resolver });

  // Function to handle form submission
  const onSubmit: SubmitHandler<LoginFormValues> = (data: LoginFormValues) => {
    const authenticate = async () => {
      setIsLoading(true);
      try {
        // Attempt to get token and login
        const { user, token } = await loginRepository.getToken(data);
        await login(user, token);
        navigate("/");
      } catch (error: any) {
        // Handle different types of errors
        if (axios.isAxiosError(error)) {
          error as AxiosError;
          switch (error.code) {
            case axios.AxiosError.ERR_BAD_REQUEST:
              setError("root.serverError", {
                type: "401",
                message: "Correo electrónico o contraseña incorrectos",
              });
              break;
            case axios.AxiosError.ERR_NETWORK:
              setError("root.serverError", {
                type: "500",
                message: "Conexión con el servidor fallida",
              });
              break;
          }
        }
      }
      setIsLoading(false);
    };
    authenticate();
  };

  // Redirect if user is already logged in
  useEffect(() => {
    if (user) {
      navigate("/");
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return { register, handleSubmit, onSubmit, errors, clearErrors };
};
