import { useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { useTranslation } from "react-i18next";
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
import {
  assignOrganizationAdmin,
  assignUnitAdmin,
  fetchAllUnitAdminById,
} from "@/super-admin/services/api/organizationAdminService";
import {
  assignOrgAdminRole,
  assignUnitAdminRole,
  removeOrgAdminRole,
  removeUnitAdminRole,
} from "@/super-admin/services/api/userRoleService";
import {
  activateUser,
  deactivateUser,
} from "@/super-admin/services/api/userService";
import { resendVerificationCode } from "@/shared/services/authService";
import {
  updateProfile,
  UpdateProfilePayload,
} from "@/user-management/services/api/employeePositionsService";

export interface OrgAdminUserRole {
  id: string;
  organizationId?: string | null;
  unitId?: string | null;
  role?: { key?: string } | null;
}

/** User row returned by GET /organizations/all-admins/:id (userRoles.role relation included). */
export interface OrgAdminUser {
  id: string;
  name?: { am?: string; en?: string };
  username?: string;
  email?: string;
  phoneNumber?: string;
  isActive: boolean;
  hasSetPassword: boolean;
  status?: string;
  createdAt?: string;
  userRoles?: OrgAdminUserRole[];
}

export const ORG_ADMINS_KEY = "orgAdmins";
export const ORG_PICKER_KEY = "orgAdminsOrgPicker";

export interface RemoveAdminInput {
  userId: string;
  /** set for org-admin removal */
  organizationId?: string;
  /** set for unit-admin removal (wins over organizationId) */
  unitId?: string;
}

export interface AddAdminInput {
  organizationId: string;
  /** set → create as unit admin of this unit instead of org admin */
  unitId?: string;
  name: { am: string; en: string };
  username: string;
  email: string;
  phoneNumber: string;
}

export const useOrgAdmins = (
  orgId?: string,
  params?: { take?: number; skip?: number },
) => {
  const queryClient = useQueryClient();
  const { t } = useTranslation();
  const { handleError, getErrorMessage } = useErrorHandler(t);

  // dialog mutations surface their API errors inline, not via toast
  const [formError, setFormError] = useState<string | null>(null);
  const [assignError, setAssignError] = useState<string | null>(null);
  const [removeError, setRemoveError] = useState<string | null>(null);
  const [toggleError, setToggleError] = useState<string | null>(null);

  const inlineError =
    (set: (message: string | null) => void) => async (err: unknown) => {
      console.error(err);
      set(await getErrorMessage(err));
    };

  const clearErrors = () => {
    setFormError(null);
    setAssignError(null);
    setRemoveError(null);
    setToggleError(null);
  };

  const {
    data: adminsResponse,
    isLoading,
    isError,
    refetch,
  } = useQuery({
    queryKey: [ORG_ADMINS_KEY, orgId, params],
    queryFn: async () => {
      const { data } = await fetchAllUnitAdminById(orgId as string, params);
      return {
        count: (data?.count ?? 0) as number,
        items: (data?.items ?? []) as OrgAdminUser[],
      };
    },
    enabled: !!orgId,
    staleTime: 5 * 60 * 1000,
    retry: false,
  });

  const invalidate = () => {
    queryClient.invalidateQueries({ queryKey: [ORG_ADMINS_KEY] });
    // picker + org tables show adminsCount — keep them fresh
    queryClient.invalidateQueries({ queryKey: [ORG_PICKER_KEY] });
    queryClient.invalidateQueries({ queryKey: ["organizations"] });
    queryClient.invalidateQueries({ queryKey: ["organizationAdmins"] });
  };

  const { mutate: addAdmin, isPending: isAdding } = useMutation({
    mutationFn: async ({
      organizationId,
      unitId,
      ...person
    }: AddAdminInput) => {
      // both iam invite endpoints create the user (employee + role +
      // SET_PASSWORD OTP in one tx); unitId decides the admin scope
      const { data } = unitId
        ? await assignUnitAdmin({ unitId, ...person })
        : await assignOrganizationAdmin({ organizationId, ...person });
      return data;
    },
    onMutate: () => setFormError(null),
    onSuccess: () => {
      toast.success(t("orgAdmins.toasts.added"));
      invalidate();
    },
    onError: inlineError(setFormError),
  });

  const { mutate: assignAdmin, isPending: isAssigning } = useMutation({
    mutationFn: async ({
      organizationId,
      userId,
      unitId,
    }: {
      organizationId: string;
      userId: string;
      /** set → grant unit-admin of this unit instead of org-admin */
      unitId?: string;
    }) => {
      const { data } = unitId
        ? await assignUnitAdminRole({ unitId, userId })
        : await assignOrgAdminRole({ organizationId, userId });
      return data;
    },
    onMutate: () => setAssignError(null),
    onSuccess: () => {
      toast.success(t("orgAdmins.toasts.assigned"));
      invalidate();
    },
    onError: inlineError(setAssignError),
  });

  const { mutate: removeAdmin, isPending: isRemoving } = useMutation({
    mutationFn: async ({ userId, organizationId, unitId }: RemoveAdminInput) => {
      const { data } = unitId
        ? await removeUnitAdminRole({ unitId, userId })
        : await removeOrgAdminRole({
            organizationId: organizationId as string,
            userId,
          });
      return data;
    },
    onMutate: () => setRemoveError(null),
    onSuccess: () => {
      toast.success(t("orgAdmins.toasts.removed"));
      invalidate();
    },
    onError: inlineError(setRemoveError),
  });

  const { mutate: resendInvite, isPending: isResending } = useMutation({
    mutationFn: async (payload: { email: string; phoneNumber: string }) => {
      const { data } = await resendVerificationCode(payload);
      return data;
    },
    onSuccess: () => {
      toast.success(t("orgAdmins.toasts.resent"));
    },
    onError: handleError,
  });

  const { mutate: toggleActive, isPending: isToggling } = useMutation({
    mutationFn: async ({ id, activate }: { id: string; activate: boolean }) => {
      const { data } = activate
        ? await activateUser(id)
        : await deactivateUser(id);
      return data;
    },
    onMutate: () => setToggleError(null),
    onSuccess: (_data, variables) => {
      toast.success(
        variables.activate
          ? t("orgAdmins.toasts.activated")
          : t("orgAdmins.toasts.deactivated"),
      );
      invalidate();
    },
    onError: inlineError(setToggleError),
  });

  const { mutate: updateAdminProfile, isPending: isUpdatingProfile } =
    useMutation({
      mutationFn: async ({
        id,
        payload,
      }: {
        id: string;
        payload: UpdateProfilePayload;
      }) => {
        const { data } = await updateProfile(payload, id);
        return data;
      },
      onMutate: () => setFormError(null),
      onSuccess: () => {
        toast.success(t("orgAdmins.toasts.profileUpdated"));
        invalidate();
      },
      onError: inlineError(setFormError),
    });

  return {
    adminsResponse,
    isLoading,
    isError,
    refetch,
    addAdmin,
    isAdding,
    assignAdmin,
    isAssigning,
    removeAdmin,
    isRemoving,
    resendInvite,
    isResending,
    toggleActive,
    isToggling,
    updateAdminProfile,
    isUpdatingProfile,
    formError,
    assignError,
    removeError,
    toggleError,
    clearErrors,
  };
};
