import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import Toast from '@arcblock/ux/lib/Toast';
import { ConfirmDialog, api, formatError } from '@blocklet/payment-react';
import type { TPrice, TProduct } from '@blocklet/payment-types';
import { useRequest, useSetState } from 'ahooks';
import noop from 'lodash/noop';
import { useNavigate } from 'react-router-dom';

import { dispatch } from 'use-bus';
import Actions from '../../../../components/actions';
import EditPrice from '../../../../components/product/edit-price';

type Props = {
  data: TPrice;
  onChange: Function;
  variant?: string;
  setAsDefault?: boolean;
  product?: TProduct | null;
};

const getCreditCurrencyConfig = async (currencyId: string) => {
  const res = await api.get(`/api/payment-currencies/${currencyId}/recharge-config`);
  return res.data;
};

export default function PriceActions({
  data,
  onChange,
  variant = 'compact',
  setAsDefault = false,
  product = null,
}: Props) {
  const { t } = useLocaleContext();
  const navigate = useNavigate();

  const canEdit = data.active;
  const canArchive = data.active;
  const canRemove = !data.locked && !setAsDefault;

  const [state, setState] = useSetState({
    action: '',
    loading: false,
  });

  const onEditPrice = async (updates: TPrice) => {
    if (Number(updates.quantity_available) > 0 && Number(updates.quantity_available) < Number(updates.quantity_sold)) {
      Toast.warning(t('admin.price.quantityAvailable.valid'));
      return;
    }
    try {
      setState({ loading: true });
      await api.put(`/api/prices/${data.id}`, updates).then((res: any) => res.data);
      Toast.success(t('common.saved'));
      dispatch('price.updated');
      onChange(state.action);
    } catch (err) {
      console.error(err);
      Toast.error(formatError(err));
      throw err;
    } finally {
      setState({ loading: false });
    }
  };
  const onArchivePrice = async () => {
    try {
      setState({ loading: true });
      await api.put(`/api/prices/${data.id}/archive`).then((res: any) => res.data);
      Toast.success(t('common.saved'));
      dispatch('price.updated');
      onChange(state.action);
    } catch (err) {
      console.error(err);
      Toast.error(formatError(err));
    } finally {
      setState({ loading: false, action: '' });
    }
  };
  const onRemovePrice = async () => {
    try {
      setState({ loading: true });
      await api.delete(`/api/prices/${data.id}`).then((res: any) => res.data);
      Toast.success(t('common.removed'));
      dispatch('price.deleted');
      onChange(state.action);
    } catch (err) {
      console.error(err);
      Toast.error(formatError(err));
    } finally {
      setState({ loading: false, action: '' });
    }
  };
  const onSetAsDefault = async () => {
    try {
      setState({ loading: true });
      await api.put(`/api/products/${data.product_id}`, { default_price_id: data.id }).then((res: any) => res.data);
      Toast.success(t('common.saveAsDefaultPriceSuccess'));
      onChange(state.action);
    } catch (err) {
      console.error(err);
      Toast.error(formatError(err));
    } finally {
      setState({ loading: false, action: '' });
    }
  };

  const onCreatePaymentLink = () => {
    navigate(`/admin/products/links?price_id=${data.id}`);
  };

  const onCreatePricingTable = () => {
    navigate(`/admin/products/pricing-tables?price_id=${data.id}`);
  };

  const creditCurrencyId = data.metadata?.credit_config?.currency_id;

  const { data: creditCurrencyConfig } = useRequest(() => getCreditCurrencyConfig(creditCurrencyId), {
    refreshDeps: [creditCurrencyId],
    ready: !!creditCurrencyId,
  });

  const onSaveAsTopupPrice = async () => {
    try {
      setState({ loading: true });
      await api.put(`/api/payment-currencies/${creditCurrencyId}/recharge-config`, {
        base_price_id: data.id,
      });

      Toast.success(t('admin.price.credit.saveSuccess'));
      onChange(state.action);
    } catch (err) {
      console.error(err);
      Toast.error(formatError(err));
    } finally {
      setState({ loading: false, action: '' });
    }
  };

  const actions = [
    {
      label: t('admin.pricing'),
      handler: noop,
      color: 'text.primary',
      disabled: true,
    },
    {
      label: t('admin.price.edit'),
      handler: () => setState({ action: 'edit' }),
      color: canEdit ? 'text.primary' : 'text.disabled',
      disabled: !canEdit,
    },
    {
      label: t('admin.price.archive'),
      handler: () => setState({ action: 'archive' }),
      color: canArchive ? 'text.primary' : 'text.disabled',
      disabled: !canArchive,
    },
    {
      label: t('admin.price.remove'),
      handler: () => setState({ action: 'remove' }),
      color: canRemove ? 'error.main' : 'text.disabled',
      disabled: !canRemove,
      divider: !setAsDefault,
    },
    {
      label: t('admin.payments'),
      handler: noop,
      color: 'text.primary',
      disabled: true,
    },
    { label: t('admin.paymentLink.add'), handler: onCreatePaymentLink, color: 'primary' },
    { label: t('admin.pricingTable.add'), handler: onCreatePricingTable, color: 'primary', disabled: !data.recurring },
  ].filter(Boolean);

  if (!setAsDefault) {
    actions.splice(4, 0, {
      label: t('admin.price.setAsDefault'),
      handler: onSetAsDefault,
      color: 'text.primary',
      disabled: false,
      divider: true,
    });
  }

  if (creditCurrencyId && creditCurrencyConfig?.recharge_config?.base_price_id !== data.id) {
    const insertIndex = !setAsDefault ? 5 : 4;
    actions.splice(insertIndex, 0, {
      label: t('admin.price.credit.saveAsBasePrice'),
      handler: onSaveAsTopupPrice,
      color: 'text.primary',
      disabled: false,
      divider: false,
    });
  }

  return (
    <>
      <Actions variant={variant} actions={actions} />
      {state.action === 'edit' && (
        <EditPrice
          // @ts-ignore
          price={data}
          onSave={onEditPrice}
          onCancel={() => setState({ action: '' })}
          productType={product?.type}
        />
      )}
      {state.action === 'archive' && (
        <ConfirmDialog
          onConfirm={onArchivePrice}
          onCancel={() => setState({ action: '' })}
          title={t('admin.price.archive')}
          message={t('admin.price.archiveTip')}
        />
      )}
      {state.action === 'remove' && (
        <ConfirmDialog
          onConfirm={onRemovePrice}
          onCancel={() => setState({ action: '' })}
          title={t('admin.price.remove')}
          message={t('admin.price.removeTip')}
        />
      )}
    </>
  );
}
