import {
  ApolloCache,
  Reference,
  useMutation,
  useQuery,
  gql,
} from '@apollo/client';

import {
  DeleteWorkspaceMutation,
  DeleteWorkspaceMutationVariables,
  TryDeleteWorkspaceQuery,
  TryDeleteWorkspaceQueryVariables,
} from 'types/graphql';
import { handleGraphQLError } from 'lib/appsync/utils';
import { UNDELETABLE_OBJECT } from 'lib/appsync/errorTypes';

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

const TRY_DELETE_WORKSPACE = gql`
  query TRY_DELETE_WORKSPACE($workspaceId: ID!) {
    confirm: tryDeleteWorkspace(workspaceId: $workspaceId) {
      ...confirmation
    }
  }
  ${fragments.confirmation}
`;

const DELETE_WORKSPACE = gql`
  mutation DELETE_WORKSPACE($workspaceId: ID!, $confirmedIds: [ID]) {
    workspace: deleteWorkspace(
      workspaceId: $workspaceId
      acceptedConsequences: $confirmedIds
    ) {
      id
    }
  }
`;

const removeExistingWorkspaceRef =
  (workspaceId: string) => (cache: ApolloCache<any>) => {
    cache.modify({
      fields: {
        allWorkspaces(existingWorkspaceRefs: Reference[], { readField }) {
          const filtered = existingWorkspaceRefs.filter(
            (workspaceRef) => readField('id', workspaceRef) !== workspaceId
          );
          return filtered;
        },
      },
    });
  };

interface DeleteWorkspaceModalProps {
  workspaceId: string;
  onComplete?: () => void;
  onDismiss?: () => void;
}

export const DeleteWorkspaceModal = ({
  workspaceId,
  onComplete,
  onDismiss,
}: DeleteWorkspaceModalProps) => {
  const { data, ...query } = useQuery<
    TryDeleteWorkspaceQuery,
    TryDeleteWorkspaceQueryVariables
  >(TRY_DELETE_WORKSPACE, {
    variables: { workspaceId },
  });

  const [mutate, mutation] = useMutation<
    DeleteWorkspaceMutation,
    DeleteWorkspaceMutationVariables
  >(DELETE_WORKSPACE, {
    update: removeExistingWorkspaceRef(workspaceId!),
  });

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

  const exception = handleGraphQLError(query.error, UNDELETABLE_OBJECT);

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

  return (
    <DeleteConfirmationModal
      title="Delete workspace?"
      message={
        exception
          ? exception.message
          : "Once you delete the workspace you can't undo it!"
      }
      confirm={data?.confirm}
      loading={query.loading}
      submitting={mutation.loading}
      onSubmit={handleDelete}
      onDismiss={onDismiss}
      submitButton={mutation.loading ? 'Deleting...' : 'Delete'}
      error={error}
    />
  );
};
