import { useMutation, useQueries, useQuery } from '@tanstack/react-query';
import { useMemo } from 'react';

import { PARTICIPANT_EXITS_ERROR, UNAUTHORIZED_ERROR } from '../constants/custom';
import api from '../services/api';
import {
  EventCampInsertPayload,
  EventFunctionAllCampPayload,
  ParticipantCampAllResponse,
  ParticipantCampInsertNewPayload,
  ParticipantCampUpdatePayload,
} from '../services/api/APIS/Events/types';
import { showFeedback } from '../services/feedback/showFeedback';
import { usePhotos } from './useCongress';
import { useHasPersonAccess } from './usePerson';

export const useCampsAccess = (token: string, userRole: string) => {
  const { data: camps, isLoading } = useUnitAllCampGet(token, userRole);
  const hasCampAccess = useMemo(() => {
    if (!camps) return false;
    return camps[0] !== UNAUTHORIZED_ERROR;
  }, [camps]);

  return { hasCampAccess, isLoading };
};

export const useEventCampStateAll = (token: string, disabled = false) => {
  return useQuery(['camp-state-list', [token]], () => api.events.eventCampStatesAllGet(token), {
    enabled: !!token && !disabled,
  });
};

export const useEventCampAll = (
  token: string,
  role: string,
  name: string,
  isFuture: string,
  year: string,
  isRelation: string,
  isChildDirect: string,
  isChildUnit: string,
  regNumber: string,
  location: string,
  disabled = false,
) => {
  return useQuery(
    [
      'camp-list',
      [
        token,
        role,
        name,
        isFuture,
        year,
        isRelation,
        isChildDirect,
        isChildUnit,
        regNumber,
        location,
      ],
    ],
    () =>
      api.events.eventCampAllGet(
        token,
        name,
        isFuture,
        year,
        isRelation,
        isChildDirect,
        isChildUnit,
        regNumber,
        location,
      ),
    {
      enabled: !!token && !disabled,
    },
  );
};

export const useEventCampDetail = (
  token: string,
  role: string,
  campId: string,
  disabled = false,
) => {
  return useQuery(
    ['camp-detail', [token, role, campId]],
    () => api.events.eventCampDetailGet(token, campId),
    {
      enabled: !!token && !disabled,
    },
  );
};

export const useUnits = (token: string, role: string, data: string[], disabled = false) => {
  return useQueries({
    queries: (data || []).map(item => ({
      queryKey: ['camp-units', item, role],
      queryFn: () => api.organizationUnit.unitDetailGet(token, item),
      enabled: !!token && !!item && !disabled,
      staleTime: Infinity,
    })),
  });
};

export const useCampDetail = (token: string, role: string, campId: string, disabled = false) => {
  const {
    data: camp,
    isLoading: isDetailLoading,
    refetch: refetchCampDetail,
  } = useEventCampDetail(token, role, campId, disabled);
  const units = useUnits(token, role, camp?.unitIds || [], disabled);

  const detail = {
    ...camp,
    units: units.map(item => item.data),
    isClosed: ['approvedLeader', 'approvedParent'].indexOf(camp?.stateId || '') !== -1,
    isEditable: ['approvedLeader', 'approvedParent'].indexOf(camp?.stateId || '') === -1,
  };

  const isLoading = isDetailLoading || units.some(item => item.isLoading);

  return { detail, isLoading, refetchCampDetail };
};

export const useEventFunctionAllCamp = (token: string, role: string, campId: string) => {
  return useQuery(
    ['camp-functions', [token, role, campId]],
    () => api.events.eventFunctionAllCampGet(token, campId),
    {
      enabled: !!token,
    },
  );
};

export const useEventCampUpdateFunction = (
  token: string,
  campId: string,
  refetchFunctions: () => void,
  goBack?: () => void,
) => {
  return useMutation(
    ['camp-date-delete', token, campId],
    (payload: EventFunctionAllCampPayload[]) =>
      api.events.eventCampUpdateFunctionPost(token, campId, payload),
    {
      onSuccess: () => {
        refetchFunctions();
        goBack && goBack();
        showFeedback({
          title: 'Složení týmu bylo úspěšně upraveno.',
          type: 'success',
        });
      },
      onError: err => {
        showFeedback({
          title:
            'Při upravování týmu došlo k chybě. Zkontrolujte prosím vaše internetové připojení.',
          type: 'danger',
          err,
        });
      },
    },
  );
};

export const useEventCampStatisticDetailGet = (
  token: string,
  campId: string,
  isEstimate: boolean,
  disabled = false,
) => {
  return useQuery(
    ['camp-statistic-detail', [token, campId, isEstimate]],
    () => api.events.eventCampStatisticDetailGet(token, campId, isEstimate),
    {
      enabled: !!token && !disabled,
    },
  );
};

export const useCampStatistics = (token: string, campId: string) => {
  const { data: statistics, isLoading: isStatisticsLoading } = useEventCampStatisticDetailGet(
    token,
    campId,
    false,
  );
  const { data: estimate, isLoading: isEstimateLoading } = useEventCampStatisticDetailGet(
    token,
    campId,
    true,
  );

  const { data: detail, isLoading: isDetailLoading } = useEventCampDetail(token, '', campId);

  const isLoading = isStatisticsLoading || isEstimateLoading || isDetailLoading;

  return { statistics, estimate, detail, isLoading };
};

export const useParticipantCampAllGet = (token: string, campId: string, disabled = false) => {
  return useQuery(
    ['camp-participant-all', [token, campId]],
    () => api.events.participantCampAllGet(token, campId),
    {
      enabled: !!token && !disabled,
    },
  );
};

export const useParticipants = (token: string, campId: string) => {
  const {
    data: participants,
    isFetching: isParticipantsLoading,
    refetch: refetchList,
  } = useParticipantCampAllGet(token, campId);
  const photos = usePhotos(token, participants || []);
  const personAccesses = useHasPersonAccess(token, participants || []);

  const list = participants?.map((item: ParticipantCampAllResponse) => {
    const photo = photos.map(item => item.data).find(logoItem => logoItem?.id === item.personId);
    const hasPersonAccess = personAccesses
      .map(item => item.data)
      .find(accessItem => accessItem?.id === item.personId)?.hasAccess;
    return {
      ...item,
      photo: photo?.photoContent || '',
      hasPersonAccess,
    };
  });

  const isLoading = isParticipantsLoading || personAccesses.some(item => item.isLoading);

  return { list, isLoading, refetchList };
};

export const useParticipantCampDeletePost = (token: string, refetchParticipants: () => void) => {
  return useMutation(
    ['participant-camp-delete', token],
    (participantId: string) => api.events.participantCampDeletePost(token, participantId),
    {
      onSuccess: () => {
        refetchParticipants();
        showFeedback({
          title: 'Účastník byl úspěšně odebrán z táboru.',
          type: 'success',
        });
      },
      onError: err => {
        showFeedback({
          title:
            'Při mazání účastníka došlo k chybě. Zkontrolujte prosím vaše internetové připojení.',
          type: 'danger',
          err,
        });
      },
    },
  );
};

export const useParticipantCampUpdatePost = (
  token: string,
  participantId: string,
  refetchParticipants: () => void,
  goBack: () => void,
) => {
  return useMutation(
    ['participant-camp-update', token, participantId],
    (payload: ParticipantCampUpdatePayload) =>
      api.events.participantCampUpdatePost(token, participantId, payload),
    {
      onSuccess: () => {
        refetchParticipants();
        goBack();
        showFeedback({
          title: 'Účastník byl úspěšně upraven.',
          type: 'success',
        });
      },
      onError: err => {
        showFeedback({
          title:
            'Při úpravě účastníka došlo k chybě. Zkontrolujte prosím vaše internetové připojení.',
          type: 'danger',
          err,
        });
      },
    },
  );
};

export const useParticipantCampInsertPost = (
  token: string,
  campId: string,
  refetchParticipants: () => void,
  goBack?: () => void,
) => {
  return useMutation(
    ['participant-camp-insert', token, campId],
    (personId: string) => api.events.participantCampInsertPost(token, campId, personId),
    {
      onSuccess: () => {
        refetchParticipants();
        goBack && goBack();
        showFeedback({
          title: `Účastní${goBack ? 'ci byly úspěšně přidáni.' : 'k byl úspěšně přidán.'}`,
          type: 'success',
        });
      },
      onError: (err: string) => {
        let message =
          'Při přidání účastníka došlo k chybě. Zkontrolujte prosím vaše internetové připojení.';
        if (err.includes(PARTICIPANT_EXITS_ERROR)) {
          message = 'Účastník již je přidán v táboře.';
        }
        showFeedback({
          title: message,
          type: 'danger',
          err,
        });
      },
    },
  );
};

export const useParticipantCampInsertNewPost = (
  token: string,
  campId: string,
  refetchParticipants: () => void,
  goBack: () => void,
) => {
  return useMutation(
    ['participant-camp-insert', token, campId],
    (payload: ParticipantCampInsertNewPayload) =>
      api.events.participantCampInsertNewPost(token, campId, payload),
    {
      onSuccess: () => {
        refetchParticipants();
        goBack();
        showFeedback({
          title: 'Účastník byl úspěšně přidán.',
          type: 'success',
        });
      },
      onError: err => {
        showFeedback({
          title:
            'Při přidání účastníka došlo k chybě. Zkontrolujte prosím vaše internetové připojení.',
          type: 'danger',
          err,
        });
      },
    },
  );
};

export const usePersonAllEventCampMultiGet = (token: string, campId: string, disabled = false) => {
  return useQuery(
    ['person-all-event-camp-multi', [token, campId]],
    () => api.organizationUnit.personAllEventCampMultiGet(token, campId),
    {
      enabled: !!token && !disabled,
    },
  );
};

export const useUnitAllCampGet = (token: string, userRole: string, disabled = false) => {
  return useQuery(
    ['unit-all-camp', token, userRole],
    () => api.organizationUnit.unitAllCampGet(token),
    {
      enabled: !!token && !disabled,
    },
  );
};

export const useCampTypeAllGet = (token: string, disabled = false) => {
  return useQuery(['camp-type-all', token], () => api.events.campTypeAllGet(token), {
    enabled: !!token && !disabled,
  });
};

export const useRegionAllGet = (token: string, disabled = false) => {
  return useQuery(['region-all', token], () => api.events.regionAllGet(token), {
    enabled: !!token && !disabled,
  });
};

export const useCampPlaceAllGet = (token: string, disabled = false) => {
  return useQuery(['camp-place-all', token], () => api.events.campPlaceAllGet(token), {
    enabled: !!token && !disabled,
  });
};

export const useEventCampAdd = (
  token: string,
  goBack: () => void,
  refetchCamps: () => void,
  refetchCampDetail: () => void,
  campId?: string,
) => {
  return useMutation(
    ['event-camp-add', [token, campId]],
    (payload: EventCampInsertPayload) => api.events.eventCampAdd(token, payload, campId),
    {
      onSuccess: () => {
        if (campId) {
          refetchCampDetail && refetchCampDetail();
        }
        refetchCamps();
        goBack();
        showFeedback({
          title: `Tábor byl úspěšně ${campId ? 'upraven' : 'přidán'}.`,
          type: 'success',
        });
      },
      onError: err => {
        showFeedback({
          title: `Při ${
            campId ? 'upravení' : 'přidání'
          } táboru došlo k chybě. Zkontrolujte prosím vaše internetové připojení.`,
          type: 'danger',
          err,
        });
      },
    },
  );
};

export const useEventCampDelete = (token: string, goBack: () => void, refetchCamps: () => void) => {
  return useMutation(
    ['event-camp-delete', [token]],
    (campId: string) => api.events.eventCampDelete(token, campId),
    {
      onSuccess: () => {
        refetchCamps();
        goBack();
        showFeedback({
          title: `Tábor byl úspěšně smazán.`,
          type: 'success',
        });
      },
      onError: err => {
        showFeedback({
          title: `Při mazání táboru došlo k chybě. Zkontrolujte prosím vaše internetové připojení.`,
          type: 'danger',
          err,
        });
      },
    },
  );
};

export const useCampEdit = (token: string, userRole: string) => {
  const { data: camps, isLoading: isCampsLoading } = useUnitAllCampGet(token, userRole);
  const { data: campTypes, isLoading: isCampTypesLoading } = useCampTypeAllGet(token);
  const { data: regions, isLoading: isRegionsLoading } = useRegionAllGet(token);
  const { data: campPlaces, isLoading: isCampPlacesLoading } = useCampPlaceAllGet(token);

  const isLoading = isCampsLoading || isCampTypesLoading || isRegionsLoading || isCampPlacesLoading;

  return { camps, campTypes, campPlaces, regions, isLoading };
};

export const useEventCampUpdateStatePost = (
  token: string,
  eventId: string,
  refetch: () => void,
) => {
  return useMutation(
    ['event-camp-state', token, eventId],
    (isClosed: boolean) =>
      isClosed
        ? api.events.eventCampUpdateOpenPost(token, eventId)
        : api.events.eventCampUpdateClosePost(token, eventId),
    {
      onSuccess: () => {
        refetch();
        showFeedback({
          title: 'Stav akce byl upraven.',
          type: 'success',
        });
      },
      onError: err => {
        showFeedback({
          title:
            'Při uzavírání stavu akce došlo k chybě. Zkontrolujte prosím vaše internetové připojení.',
          type: 'danger',
          err,
        });
      },
    },
  );
};
