import { useQuery } from '@tanstack/react-query';
import {
  deleteUserProgressByItem,
  listUserProgress,
  upsertUserProgress,
} from '@/shared/api/userProgress';
import {
  USER_PROGRESS_QUERY_KEYS,
  USER_PROGRESS_TYPES,
} from '@/shared/constants/userProgress';
import {
  toLearnedSignIds,
  toProgressItemIds,
} from '@/business/user-progress/mappers';
import {
  ClassroomStrategyFavoritesState,
  LearnedSignsState,
} from '@/business/user-progress/types';
import { selectApiListRows } from '@/shared/business/apiListRows';
import { useInvalidatingMutation } from '@/shared/business/queryMutations';

const EMPTY_LEARNED_SIGNS = new Set<string>();
const EMPTY_CLASSROOM_STRATEGY_FAVORITES = new Set<string>();

interface UseLearnedSignsProgressOptions {
  readonly enabled?: boolean;
}

export function useLearnedSignsProgress(
  options: UseLearnedSignsProgressOptions = {},
): LearnedSignsState {
  const enabled = options.enabled ?? true;
  const progressQuery = useQuery({
    queryKey: USER_PROGRESS_QUERY_KEYS.signProgress,
    enabled,
    queryFn: () => selectApiListRows(
      listUserProgress(USER_PROGRESS_TYPES.signLearned),
      toLearnedSignIds,
    ),
  });

  const saveMutation = useInvalidatingMutation({
    mutationFn: ({ id, word }: { readonly id: string; readonly word: string }) => upsertUserProgress({
      progress_type: USER_PROGRESS_TYPES.signLearned,
      item_id: id,
      value: word,
    }),
    invalidateQueryKey: USER_PROGRESS_QUERY_KEYS.signProgress,
  });

  const deleteMutation = useInvalidatingMutation({
    mutationFn: (id: string) => deleteUserProgressByItem(USER_PROGRESS_TYPES.signLearned, id),
    invalidateQueryKey: USER_PROGRESS_QUERY_KEYS.signProgress,
  });

  async function toggleLearnedSign(id: string, word: string) {
    if (!enabled) {
      return;
    }

    const learnedSignIds = progressQuery.data ?? EMPTY_LEARNED_SIGNS;

    if (learnedSignIds.has(id)) {
      await deleteMutation.mutateAsync(id);
      return;
    }

    await saveMutation.mutateAsync({ id, word });
  }

  return {
    learnedSignIds: progressQuery.data ?? EMPTY_LEARNED_SIGNS,
    isLoading: progressQuery.isLoading,
    isSaving: saveMutation.isPending || deleteMutation.isPending,
    error: progressQuery.error || saveMutation.error || deleteMutation.error,
    toggleLearnedSign,
  };
}

interface UseClassroomStrategyFavoritesOptions {
  readonly enabled?: boolean;
}

export function useClassroomStrategyFavorites(
  options: UseClassroomStrategyFavoritesOptions = {},
): ClassroomStrategyFavoritesState {
  const enabled = options.enabled ?? true;
  const progressQuery = useQuery({
    queryKey: USER_PROGRESS_QUERY_KEYS.classroomStrategyFavorites,
    enabled,
    queryFn: () => selectApiListRows(
      listUserProgress(USER_PROGRESS_TYPES.classroomStrategyFavorite),
      toProgressItemIds,
    ),
  });

  const saveMutation = useInvalidatingMutation({
    mutationFn: ({ id, title }: { readonly id: string; readonly title: string }) => upsertUserProgress({
      progress_type: USER_PROGRESS_TYPES.classroomStrategyFavorite,
      item_id: id,
      value: title,
    }),
    invalidateQueryKey: USER_PROGRESS_QUERY_KEYS.classroomStrategyFavorites,
  });

  const deleteMutation = useInvalidatingMutation({
    mutationFn: (id: string) => deleteUserProgressByItem(
      USER_PROGRESS_TYPES.classroomStrategyFavorite,
      id,
    ),
    invalidateQueryKey: USER_PROGRESS_QUERY_KEYS.classroomStrategyFavorites,
  });

  async function toggleFavoriteStrategy(id: string, title: string) {
    if (!enabled) {
      return;
    }

    const favoriteStrategyIds = progressQuery.data ?? EMPTY_CLASSROOM_STRATEGY_FAVORITES;

    if (favoriteStrategyIds.has(id)) {
      await deleteMutation.mutateAsync(id);
      return;
    }

    await saveMutation.mutateAsync({ id, title });
  }

  return {
    favoriteStrategyIds: progressQuery.data ?? EMPTY_CLASSROOM_STRATEGY_FAVORITES,
    isLoading: progressQuery.isLoading,
    isSaving: saveMutation.isPending || deleteMutation.isPending,
    error: progressQuery.error || saveMutation.error || deleteMutation.error,
    toggleFavoriteStrategy,
  };
}
