import {
  ApolloCache,
  FetchResult,
  Reference,
  useMutation,
  useQuery,
  gql,
} from '@apollo/client';
import { useFragmentQuery } from 'lib/apollo/useFragmentQuery';
import { audience_extended } from '../schema/fragments';
import {
  AudienceExtendedFragment,
  DeleteAudienceMutation,
  DeleteAudienceMutationVariables,
  TryDeleteAudienceQuery,
  TryDeleteAudienceQueryVariables,
} from 'types/graphql';
import { handleGraphQLError } from 'lib/appsync/utils';
import { SERVICE_INFO_ERROR } from 'lib/appsync/errorTypes';

import { InfoModal } from 'components/modals/InfoModal';
import {
  DeleteConfirmationModal,
  fragments,
} from 'components/modals/confirmation';
import { call } from 'utils/call';

const TRY_DELETE_AUDIENCE = gql`
  query TRY_DELETE_AUDIENCE($audienceId: ID!) {
    confirm: tryFbDeleteAudience(audienceId: $audienceId) {
      ...confirmation
    }
  }
  ${fragments.confirmation}
`;

const DELETE_AUDIENCE = gql`
  mutation DELETE_AUDIENCE($audienceId: ID!, $confirmedIds: [ID]) {
    audience: fbDeleteAudience(
      audienceId: $audienceId
      acceptedConsequences: $confirmedIds
    ) {
      id
    }
  }
`;

const deleteExistingAudienceRef = (
  cache: ApolloCache<object>,
  { data }: FetchResult<DeleteAudienceMutation>
) => {
  const audienceId = data?.audience?.id;
  if (!audienceId) return;
  cache.modify({
    fields: {
      fbListAudiences(existingAudiencesRefs: Reference[], { readField }) {
        const filtered = existingAudiencesRefs.filter(
          (audienceRef) => audienceId !== readField('id', audienceRef)
        );
        return filtered;
      },
    },
  });
};

interface DeleteAudienceModalProps {
  audienceId: string;
  onComplete?: () => void;
  onDismiss?: () => void;
}

export const DeleteAudienceModal = ({
  audienceId,
  onComplete,
  onDismiss,
}: DeleteAudienceModalProps) => {
  const audience = useFragmentQuery<AudienceExtendedFragment>(
    audience_extended,
    audienceId
  );

  const { data, ...query } = useQuery<
    TryDeleteAudienceQuery,
    TryDeleteAudienceQueryVariables
  >(TRY_DELETE_AUDIENCE, {
    variables: { audienceId },
  });

  const [deleteAudience, mutation] = useMutation<
    DeleteAudienceMutation,
    DeleteAudienceMutationVariables
  >(DELETE_AUDIENCE, {
    update: deleteExistingAudienceRef,
  });

  const handleDelete = async (confirmedIds: string[]) => {
    try {
      await deleteAudience({ variables: { audienceId, confirmedIds } });
      call(onComplete);
      call(onDismiss);
    } catch (error) {
      console.error(error);
    }
  };

  const serviceError = handleGraphQLError(mutation.error, SERVICE_INFO_ERROR);
  if (serviceError) {
    return (
      <InfoModal
        title="Something went wrong"
        message={serviceError.message}
        onDismiss={onDismiss}
      />
    );
  }

  const error = query.error || mutation.error;

  return (
    <DeleteConfirmationModal
      title="Delete audience?"
      message={
        <span>
          Audience <b>{audience?.name}</b> will be removed from Facebook. Any
          existing ads using this audience will be stopped and cannot be
          restarted.
        </span>
      }
      confirm={data?.confirm}
      loading={query.loading}
      submitting={mutation.loading}
      onSubmit={handleDelete}
      onDismiss={onDismiss}
      submitButton={mutation.loading ? 'Deleting...' : 'Delete'}
      error={error}
    />
  );
};
