import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { authService } from "../services/auth.service";
import { LoginRequest } from "../types";
import { useAppDispatch } from "@/lib/store";
import { setCurrentUser, clearCurrentUser } from "../slices/authSlice";
import { TokenService } from "@/lib/axios";
import { useEffect } from "react";
import { showToast } from "@/lib/toast";

export const authKeys = {
  currentUser: ["auth", "currentUser"] as const,
};

export const useCurrentUser = () => {
  const dispatch = useAppDispatch();
  const hasToken =
    typeof window !== "undefined" ? !!TokenService.getAccessToken() : false;

  useEffect(() => {
    if (!hasToken) {
      dispatch(clearCurrentUser());
    }
  }, [hasToken, dispatch]);

  return useQuery({
    queryKey: authKeys.currentUser,
    queryFn: async () => {
      try {
        const user = await authService.getCurrentUser();
        dispatch(setCurrentUser(user));
        return user;
      } catch (err) {
        dispatch(clearCurrentUser());
        throw err;
      }
    },
    enabled: hasToken,
    retry: false,
  });
};

export const useUpdateProfile = () => {
  const dispatch = useAppDispatch();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (payload: { name?: string; phone?: string }) =>
      authService.updateProfile(payload),
    onSuccess: (user) => {
      dispatch(setCurrentUser(user));
      qc.invalidateQueries({ queryKey: authKeys.currentUser });
      showToast.success("Profile updated successfully!");
    },
    onError: (error: any) => {
      const msg =
        error?.response?.data?.error ||
        error?.response?.data?.message ||
        "Failed to update profile";
      showToast.error(msg);
    },
  });
};

export const useUploadAvatar = () => {
  const dispatch = useAppDispatch();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (file: File) => authService.uploadAvatar(file),
    onSuccess: (user) => {
      dispatch(setCurrentUser(user));
      qc.invalidateQueries({ queryKey: authKeys.currentUser });
      showToast.success("Avatar updated!");
    },
    onError: () => showToast.error("Failed to upload avatar"),
  });
};

export const useRemoveAvatar = () => {
  const dispatch = useAppDispatch();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: () => authService.removeAvatar(),
    onSuccess: (user) => {
      dispatch(setCurrentUser(user));
      qc.invalidateQueries({ queryKey: authKeys.currentUser });
      showToast.success("Avatar removed!");
    },
    onError: () => showToast.error("Failed to remove avatar"),
  });
};

export const useLogin = () => {
  return useMutation({
    mutationFn: (data: LoginRequest) => authService.login(data),
    onSuccess: () => {
      showToast.success("Login successful");
    },
    onError: (error: any) => {
      showToast.error(error?.response?.data?.message || "Invalid credentials");
    },
  });
};

export const useRegister = () => {
  return useMutation({
    mutationFn: (data: any) => authService.register(data),
    onSuccess: () => {
      showToast.success("OTP sent to your email. Please verify to continue.");
    },
    onError: (error: any) => {
      const status = error?.response?.status;
      // 409 conflict and field validation errors are shown inline in the form
      if (status === 409 || error?.response?.data?.details?.fieldErrors) return;
      showToast.error(error?.response?.data?.message || "Registration failed");
    },
  });
};

export const useVerifyOtp = () => {
  const dispatch = useAppDispatch();

  return useMutation({
    mutationFn: (data: { email: string; otp: string; purpose?: string }) =>
      authService.verifyOtp(data),
    onSuccess: () => {
      // dispatch happens in component onSuccess AFTER navigation
      // to prevent GuestGuard from redirecting before router.push fires
    },
    onError: () => {
      // error handled in component's onError for inline display
    },
  });
};

export const useLogout = () => {
  const dispatch = useAppDispatch();

  return useMutation({
    mutationFn: () => authService.logout(),
    onSuccess: () => {
      dispatch(clearCurrentUser());
      showToast.success("Logged out");
    },
  });
};

export const useForgotPassword = () => {
  return useMutation({
    mutationFn: (email: string) => authService.forgotPassword(email),
    onSuccess: () => {
      showToast.success("Password reset OTP sent to your email.");
    },
    onError: (error: any) => {
      const fieldErrors = error?.response?.data?.details?.fieldErrors;
      if (fieldErrors && Object.keys(fieldErrors).length > 0) {
        const firstError = Object.values(fieldErrors)[0];
        showToast.error(
          Array.isArray(firstError)
            ? firstError[0]
            : (firstError as string) || "Request failed",
        );
      } else {
        showToast.error(
          error?.response?.data?.message || "Failed to send reset email",
        );
      }
    },
  });
};

export const useResetPassword = () => {
  return useMutation({
    mutationFn: (data: { email: string; otp: string; newPassword: string }) =>
      authService.resetPassword(data),
    onSuccess: () => {
      showToast.success("Password reset successfully. You can now log in.");
    },
    onError: (error: any) => {
      const fieldErrors = error?.response?.data?.details?.fieldErrors;
      if (fieldErrors && Object.keys(fieldErrors).length > 0) {
        const firstError = Object.values(fieldErrors)[0];
        showToast.error(
          Array.isArray(firstError)
            ? firstError[0]
            : (firstError as string) || "Reset failed",
        );
      } else {
        showToast.error(
          error?.response?.data?.message || "Password reset failed",
        );
      }
    },
  });
};

export const useChangePassword = () => {
  return useMutation({
    mutationFn: (data: { currentPassword: string; newPassword: string }) =>
      authService.changePassword(data.currentPassword, data.newPassword),
    onSuccess: () => {
      showToast.success("Password changed successfully.");
    },
    onError: (error: any) => {
      const msg =
        error?.response?.data?.error ||
        error?.response?.data?.message ||
        "Failed to change password";
      showToast.error(msg);
    },
  });
};
