import { useMutation } from '@apollo/client';
import { CURRENT_PACKAGE } from 'components/billing/schema/queries';
import {
  CANCEL_SUBSCRIPTION,
  CANCEL_CHANGE,
} from 'components/billing/schema/mutations';
import {
  CancelChangeMutation,
  CancelChangeMutationVariables,
  CancelSubscriptionMutation,
  CancelSubscriptionMutationVariables,
} from 'types/graphql';

import { Badge, Box, Button, Spinner, Text } from 'components/common';
import { ModalContainer } from 'components/modals';
import { formatDate } from 'utils';

interface MutationModalProps {
  title: string;
  message?: React.ReactNode;
  onAccept?: () => void;
  onDismiss?: () => void;
  loading: boolean;
  success: boolean;
  error?: Error;
}

export const MutationModal = ({
  title,
  message,
  onAccept,
  onDismiss,
  loading,
  success,
  error,
}: MutationModalProps) => {
  return (
    <ModalContainer title={title}>
      <Box spacingY={4}>
        {message}
        {error?.message && (
          <Text className="c-red" size="s">
            {error.message}
          </Text>
        )}
        {!success ? (
          <Box display="flex" spacing={2}>
            <Button onClick={onDismiss} color="gray" block>
              No
            </Button>
            <Button onClick={onAccept} color="red" block disabled={loading}>
              {!error ? 'Yes' : 'Try again'}
            </Button>
          </Box>
        ) : (
          <Box>
            <Button onClick={onDismiss} color="gray" block>
              Close
            </Button>
          </Box>
        )}
      </Box>
      <Spinner show={loading} />
    </ModalContainer>
  );
};

interface CancelSubscriptionModalProps {
  name: string;
  hasScheduledChange: boolean;
  onDismiss?: () => void;
}

export const CancelSubscriptionModal = ({
  name,
  hasScheduledChange,
  onDismiss,
}: CancelSubscriptionModalProps) => {
  const [cancel, { data, error, loading }] = useMutation<
    CancelSubscriptionMutation,
    CancelSubscriptionMutationVariables
  >(CANCEL_SUBSCRIPTION, {
    refetchQueries: [{ query: CURRENT_PACKAGE }],
    awaitRefetchQueries: true,
  });

  const cancelSubscription = async () => {
    try {
      await cancel();
    } catch (error) {
      console.log(error);
    }
  };

  function renderMessage(nextPayment: string) {
    const nextPaymentDate = formatDate(nextPayment);
    return (
      <Box spacingY={2}>
        <Text size="s">
          Your <b>{name}</b> subscription is canceled and becomes effective as
          of <b>{nextPaymentDate}</b>.
        </Text>
        {hasScheduledChange && (
          <Text size="s">
            {/* Also, your scheduled change to your active subscription is canceled. */}
            Also, your scheduled change to <b>{name}</b> subscription is
            canceled.
          </Text>
        )}
        <Text size="s">
          You can still use FanSifter until <b>{nextPaymentDate}</b>. To keep
          using FanSifter after that, reactivate your plan.
        </Text>
      </Box>
    );
  }

  const confirm = data === undefined || data === null;

  return (
    <MutationModal
      title={confirm ? 'Cancel subscription?' : 'Subscription is canceled'}
      message={
        confirm ? (
          <Box spacingY={2}>
            <Text size="s">
              When you cancel your{' '}
              <Badge className="fz12" bold uppercase>
                active
              </Badge>{' '}
              subscription, the cancellation becomes effective at the end of the
              billing period. This means your future payments are canceled, but
              you can still use FanSifter until the end of the paid billing
              period.
            </Text>
            {hasScheduledChange && (
              <Text size="s">
                This also cancels your{' '}
                <Badge color="gray" className="fz12" bold uppercase>
                  scheduled
                </Badge>{' '}
                change to your active subscription.
              </Text>
            )}
          </Box>
        ) : (
          renderMessage(data.subscription[0].nextPayment!) // TODO refactor 'nextPayment' prop
        )
      }
      loading={loading}
      success={!confirm}
      error={error}
      onAccept={cancelSubscription}
      onDismiss={onDismiss}
    />
  );
};

interface CancelChangeModalProps {
  name: string;
  onDismiss?: () => void;
}

export const CancelChangeModal = ({
  name,
  onDismiss,
}: CancelChangeModalProps) => {
  const [cancel, { data, error, loading }] = useMutation<
    CancelChangeMutation,
    CancelChangeMutationVariables
  >(CANCEL_CHANGE, {
    refetchQueries: [{ query: CURRENT_PACKAGE }],
    awaitRefetchQueries: true,
  });

  const cancelSubscription = async () => {
    try {
      await cancel();
    } catch (error) {
      console.log(error);
    }
  };

  function renderMessage() {
    return (
      <Box spacingY={2}>
        <Text size="s">
          Your scheduled change for the <b>{name}</b> subscription is canceled.
          Your{' '}
          <Badge className="fz12" bold uppercase>
            active
          </Badge>{' '}
          subscription automatically extends at the end of the billing period.
        </Text>
      </Box>
    );
  }

  const confirm = data === undefined;

  return (
    <MutationModal
      title={confirm ? 'Cancel scheduled change?' : 'Succesfully canceled'}
      message={
        confirm ? (
          <Box spacingY={2}>
            <Text size="s">
              When you cancel your scheduled change for the{' '}
              <Badge className="fz12" bold uppercase>
                active
              </Badge>{' '}
              subscription, your{' '}
              <Badge className="fz12" bold uppercase>
                active
              </Badge>{' '}
              subscription automatically extends at the end of the billing
              period.
            </Text>
          </Box>
        ) : (
          renderMessage()
        )
      }
      loading={loading}
      success={!confirm}
      error={error}
      onAccept={cancelSubscription}
      onDismiss={onDismiss}
    />
  );
};
