import {
  QueryClient,
  useMutation,
  useQuery,
  useQueryClient,
} from "@tanstack/react-query";
import {
  CreatePositionTypePayload,
  PositionRequest,
  positionTypeService,
  UpdatePositionTypePayload,
} from "../services/api/positionTypesService";
import { toast } from "sonner";
import { useTranslation } from "react-i18next";
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
import {
  PositionTypeDto,
  PositionTypesListResponse,
} from "../dto/positions/positionType";

interface positionParams {
  take: number;
  skip: number;
  orderBy: string;
  order?: string;
}

interface UsePositionTypeManagerProps {
  id?: string;
  unitId?: string;
  params?: positionParams; // 👈 we expected query params to be passed like this
}

/**
 * Every cache key this hook writes under. React Query matches key prefixes
 * element by element, so `["position-type"]` does NOT reach
 * `["position-types-common", ...]` — each root has to be listed. Anything that
 * mutates a position type should call this rather than hand-picking keys, or
 * the department pickers (which read the "-common" queries) go stale.
 */
export const invalidatePositionTypeQueries = (queryClient: QueryClient) => {
  ["position-types", "position-type", "position-types-common"].forEach(
    (root) => queryClient.invalidateQueries({ queryKey: [root] }),
  );
};

export const usePositionTypes = ({
  id,
  params = {
    take: 1000,
    skip: 0,
    orderBy: "createdAt:Desc",
  },
  unitId,
}: UsePositionTypeManagerProps = {}) => {
  const queryClient = useQueryClient();
  const { t } = useTranslation();
  const { handleError } = useErrorHandler(t);
  const invalidateAll = () => invalidatePositionTypeQueries(queryClient);
  const { data, isLoading, isError, refetch } = useQuery({
    queryKey: ["position-types", params],
    queryFn: () => positionTypeService.getAll(params).then((res) => res.data),
  });
  // Single Position Type (for edit)
  const {
    data: positionType,
    isLoading: isLoadingSingle,
    isError: isErrorSingle,
    refetch: refetchSingle,
  } = useQuery<PositionTypeDto>({
    queryKey: ["position-type", id],
    queryFn: () => positionTypeService.getById(id!).then((res) => res.data),
    enabled: !!id,
  });
  const {
    data: positionTypeByUnitId,
    isLoading: isLoadingPosition,
    isError: isErrorPosition,
    refetch: refetchPosition,
  } = useQuery<PositionTypesListResponse | undefined>({
    queryKey: ["position-type", unitId, params],
    queryFn: async () => {
      if (!unitId) return undefined;
      const res = await positionTypeService.getByUnitId(unitId, params);
      return res.data as PositionTypesListResponse | undefined;
    },
    enabled: !!unitId,
  });

  // Common types with unit ID (includes both unit-specific and common types)
  const {
    data: commonPositionTypes,
    isLoading: isLoadingCommonTypes,
    isError: isErrorCommonTypes,
    refetch: refetchCommonTypes,
  } = useQuery<PositionTypesListResponse | undefined>({
    queryKey: ["position-types-common", unitId, params],
    queryFn: async () => {
      if (!unitId) return undefined;
      const res = await positionTypeService.getCommonTypesById(unitId, params);
      return res.data as PositionTypesListResponse | undefined;
    },
    enabled: !!unitId,
  });

  // Create
  const createPositionType = useMutation({
    mutationFn: (payload: CreatePositionTypePayload) =>
      positionTypeService.create(payload),
    onSuccess: () => {
      toast.success(t("contentManagement.positionTypeCreated"));
      invalidateAll();
    },
    onError: (error) => {
      handleError(error);
    },
  });

  // Update. IAM answers 403 `position_type_not_allowed_to_update` for built-in
  // (isSystem) types, so the error has to reach the user.
  const updatePositionType = useMutation({
    mutationFn: ({
      id,
      data,
    }: {
      id: string;
      data: UpdatePositionTypePayload;
    }) => positionTypeService.update(id, data),
    onSuccess: () => {
      toast.success(t("contentManagement.positionTypeUpdated"));
      invalidateAll();
    },
    onError: (error) => {
      handleError(error);
    },
  });

  //update positon from to
  const updatePositionTypeFromTo = useMutation({
    mutationFn: ({ toId, fromId }: { toId: string; fromId: string }) =>
      positionTypeService.updateFromto(toId, fromId),
    onSuccess: () => {
      toast.success(t("contentManagement.positionTypeMigrated"));
      invalidateAll();
    },
    onError: (error) => {
      handleError(error);
    },
  });
  //update all postions
  const migratePositionsByPositions = useMutation({
    mutationFn: ({ id, data }: { id: string; data: PositionRequest }) =>
      positionTypeService.updateByPostion(id, data),
    onSuccess: () => {
      toast.success(t("contentManagement.positionTypeMigrated"));
      invalidateAll();
    },
    onError: (error) => {
      handleError(error);
    },
  });

  // Delete. Also 403s for built-in types.
  const deletePositionType = useMutation({
    mutationFn: (id: string) => positionTypeService.delete(id),
    onSuccess: () => {
      toast.success(t("contentManagement.positionTypeDeleted"));
      invalidateAll();
    },
    onError: (error) => {
      handleError(error);
    },
  });

  return {
    positionTypes: data?.items ?? [],
    positionTypeResponse: data,
    isLoading,
    isError,
    refetch,
    // single
    positionType,
    isLoadingSingle,
    isErrorSingle,
    refetchSingle,

    // mutations
    createPositionType,
    updatePositionType,
    deletePositionType,
    positionTypeByUnitId,
    migratePositionsByPositions,
    updatePositionTypeFromTo,
    refetchPosition,
    isErrorPosition,
    isLoadingPosition,
    // common types with unit ID
    commonPositionTypes: commonPositionTypes?.items ?? [],
    isLoadingCommonTypes,
    isErrorCommonTypes,
    refetchCommonTypes,
  };
};
