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

const EMPTY_LEARNED_SIGNS = new Set<string>();

export function useLearnedSignsProgress(): LearnedSignsState {
  const progressQuery = useQuery({
    queryKey: USER_PROGRESS_QUERY_KEYS.signProgress,
    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) {
    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,
  };
}

export function useZoneCheckIn(): ZoneCheckInState {
  const progressQuery = useQuery({
    queryKey: USER_PROGRESS_QUERY_KEYS.zoneCheckin,
    queryFn: () => selectApiListRows(
      listUserProgress(
        USER_PROGRESS_TYPES.zoneCheckin,
        ZONE_CHECKIN_ITEM_ID,
      ),
      (rows) => toZoneColor(rows[0]?.value || null),
    ),
  });

  const saveMutation = useInvalidatingMutation({
    mutationFn: (zone: ZoneColor) => upsertUserProgress({
      progress_type: USER_PROGRESS_TYPES.zoneCheckin,
      item_id: ZONE_CHECKIN_ITEM_ID,
      value: zone,
    }),
    invalidateQueryKey: USER_PROGRESS_QUERY_KEYS.zoneCheckin,
  });

  const deleteMutation = useInvalidatingMutation({
    mutationFn: () => deleteUserProgressByItem(
      USER_PROGRESS_TYPES.zoneCheckin,
      ZONE_CHECKIN_ITEM_ID,
    ),
    invalidateQueryKey: USER_PROGRESS_QUERY_KEYS.zoneCheckin,
  });

  async function setZone(zone: ZoneColor) {
    await saveMutation.mutateAsync(zone);
  }

  async function resetZone() {
    await deleteMutation.mutateAsync();
  }

  return {
    currentZone: progressQuery.data ?? null,
    isLoading: progressQuery.isLoading,
    isSaving: saveMutation.isPending || deleteMutation.isPending,
    error: progressQuery.error || saveMutation.error || deleteMutation.error,
    setZone,
    resetZone,
  };
}
