// Import necessary modules and components
import { useState } from "react";
import { ResetPasswordValues } from "../../data/datasource/api/entities/reset_password_values";
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 axios, { AxiosError } from "axios";
import { toast } from "react-toastify";
import { usePasswoordVisibility } from "./usePasswordVisibility";

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

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

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

  // Validate code
  if (!data.code) {
    errors.code = {
      type: "required",
      message: "El código es requerido",
    };
  } else {
    if (data.code.toString().length !== 6) {
      errors.code = {
        type: "required",
        message: "El código debe ser de 6 dígitos",
      };
    } else {
      const numberPattern = /^[0-9]+$/;
      if (!numberPattern.test(data.code.toString())) {
        errors.code = {
          type: "validate",
          message: "El código debe contener solo números",
        };
      }
    }
  }

  // Validate new password and confirmation
  if (!data.newPassword) {
    errors.newPassword = {
      type: "required",
      message: "Se requiere una nueva contraseña",
    };
  } else if (data.confirmNewPassword !== data.newPassword) {
    errors.confirmNewPassword = {
      type: "validate",
      message: "Las contraseñas deben coincidir",
    };
  }

  if (!data.confirmNewPassword) {
    errors.confirmNewPassword = {
      type: "required",
      message: "Se requiere confirmar la nueva contraseña",
    };
  }

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

// Custom hook for reset password functionality
export const useResetPassword = (handleClickToClose?: () => void) => {
  const [step, setStep] = useState(1);
  const [isChanging, setIsChanging] = useState(false);
  const {
    register,
    formState: { errors },
    handleSubmit,
    getValues,
    setError,
  } = useForm<ResetPasswordValues>({ resolver: resolver });
  const {
    values: valuesNewPassword,
    handleClickShowPassword: handleClickShowNewPassword,
    handleMouseDownPassword: handleMouseDownNewPassword,
  } = usePasswoordVisibility();
  const {
    values: valuesNewPasswordConfirm,
    handleClickShowPassword: handleClickShowNewPasswordConfirm,
    handleMouseDownPassword: handleMouseDownNewPasswordConfirm,
  } = usePasswoordVisibility();
  const [animating, setAnimating] = useState(false);

  // Handle email submission
  const handleSubmitEmail = () => {
    const fetch = async () => {
      try {
        await adminRepository.generateResetCode(getValues("email")).then(() => {
          setAnimating(true);
          setIsChanging(true);
          setTimeout(() => {
            setStep(2);
            setIsChanging(false);
            setAnimating(false);
          }, 500);
        });
      } 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: "Enviando correo...",
      success: "Se ha enviado el correo",
      error: {
        render({ data }) {
          return (data as Error).message;
        },
      },
    });
  };

  // Handle password submission
  const onSubmitPassword: SubmitHandler<ResetPasswordValues> = (
    data: ResetPasswordValues
  ) => {
    const fetch = async () => {
      try {
        await adminRepository.resetPassword(data).then(() => {
          if (handleClickToClose) {
            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("code", {
                type: "validate",
                message: "El código no es correcto",
              });
              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: "La contraseña se ha cambiado",
      error: {
        render({ data }) {
          return (data as Error).message;
        },
      },
    });
  };

  return {
    step,
    animating,
    handleSubmitEmail,
    onSubmitPassword,
    isChanging,
    register,
    errors,
    handleSubmit,
    valuesNewPassword,
    valuesNewPasswordConfirm,
    handleClickShowNewPassword,
    handleClickShowNewPasswordConfirm,
    handleMouseDownNewPassword,
    handleMouseDownNewPasswordConfirm,
  };
};
