import Dialog from '@arcblock/ux/lib/Dialog';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import Toast from '@arcblock/ux/lib/Toast';
import { api, formatError, findCurrency, usePaymentContext } from '@blocklet/payment-react';
import { Button, Box, Typography, CircularProgress, Stack } from '@mui/material';
import { FormProvider, useForm } from 'react-hook-form';
import { dispatch } from 'use-bus';
import { useEffect } from 'react';
import { fromUnitToToken } from '@ocap/util';

import PromotionCodeForm, {
  PromotionCodeData,
  DEFAULT_PROMOTION_CODE,
} from '../../../../components/promotion/promotion-code-form';

type PromotionCodeFormData = PromotionCodeData;

interface Props {
  open: boolean;
  onClose: () => void;
  onSubmit?: () => void;
  couponId: string;
  promotionCode?: any; // For editing
  isEditing?: boolean;
  couponType?: 'percentage' | 'fixed_amount';
  availableCurrencies?: Array<{ id: string; symbol: string; name: string }>;
}

export default function PromotionCodeModal({
  open,
  onClose,
  onSubmit: onSubmitCallback = () => {},
  couponId,
  promotionCode = null,
  isEditing = false,
  availableCurrencies = [],
}: Omit<Props, 'couponType'>) {
  const { t } = useLocaleContext();
  const { settings } = usePaymentContext();

  const methods = useForm<PromotionCodeFormData>({
    mode: 'onChange',
    defaultValues: DEFAULT_PROMOTION_CODE,
  });

  const {
    handleSubmit,
    reset,
    formState: { isSubmitting },
  } = methods;

  // Reset form when modal opens or promotion code changes
  useEffect(() => {
    if (open) {
      if (isEditing && promotionCode) {
        // Keep currency_options in object format for direct use
        const convertedCurrencyOptions: Record<string, { minimum_amount: number }> = {};
        const minimumAmountCurrency = promotionCode.restrictions?.minimum_amount_currency
          ? findCurrency(settings.paymentMethods, promotionCode.restrictions.minimum_amount_currency)
          : null;
        const minimumAmount = promotionCode.restrictions?.minimum_amount
          ? parseFloat(fromUnitToToken(promotionCode.restrictions.minimum_amount, minimumAmountCurrency?.decimal || 0))
          : undefined;
        let requireMinimumAmount = false;

        if (promotionCode.restrictions?.currency_options) {
          const currencyEntries = Object.entries(promotionCode.restrictions.currency_options);
          requireMinimumAmount = currencyEntries.length > 0;
          currencyEntries.forEach(([currencyId, optionData]) => {
            const currency = findCurrency(settings.paymentMethods, currencyId);
            let amount = 0;
            if (optionData && typeof optionData === 'object' && 'minimum_amount' in optionData) {
              const optionMinimumAmount = (optionData as any).minimum_amount;
              if (currency && optionMinimumAmount) {
                amount = parseFloat(fromUnitToToken(optionMinimumAmount || '0', currency.decimal));
              } else {
                amount = optionMinimumAmount || 0;
              }
            }

            convertedCurrencyOptions[currencyId] = {
              minimum_amount: amount,
            };
          });
        }

        // Populate form with existing data for editing
        reset({
          code: promotionCode.code || '',
          active: promotionCode.active ?? true,
          max_redemptions: promotionCode.max_redemptions || undefined,
          description: promotionCode.description || '',
          expires_at: promotionCode.expires_at
            ? new Date(promotionCode.expires_at * 1000).toISOString().slice(0, 16)
            : '',
          verification_type: promotionCode.verification_type || 'code',
          limit_number_redemptions: !!promotionCode.max_redemptions,
          add_expiration_date: !!promotionCode.expires_at,
          restrictions: {
            first_time_transaction: promotionCode.restrictions?.first_time_transaction || false,
            require_minimum_amount: requireMinimumAmount,
            minimum_amount: minimumAmount,
            minimum_amount_currency: minimumAmountCurrency?.id,
            currency_options: convertedCurrencyOptions,
          },
          customer_dids: promotionCode.customer_dids || [],
          nft_addresses: promotionCode.nft_config?.addresses || [],
          nft_tags: promotionCode.nft_config?.tags || [],
          trusted_issuers: promotionCode.nft_config?.trusted_issuers || [],
          trusted_parents: promotionCode.nft_config?.trusted_parents || [],
          min_balance: promotionCode.nft_config?.min_balance || 1,
          vc_roles: promotionCode.vc_config?.roles || [],
          vc_trusted_issuers: promotionCode.vc_config?.trusted_issuers || [],
        });
      } else {
        // Reset to default values for creating
        reset(DEFAULT_PROMOTION_CODE);
      }
    }
  }, [open, isEditing, promotionCode, reset, settings.paymentMethods]);

  const onSubmit = async (data: PromotionCodeFormData) => {
    try {
      const payload: any = {
        active: data.active,
        verification_type: data.verification_type,
        restrictions: data.restrictions,
        description: data.description,
        metadata: {},
      };

      if (!isEditing) {
        payload.coupon_id = couponId;
      }

      // Only include custom code if provided, otherwise let backend generate
      if (data.code && data.code.trim()) {
        payload.code = data.code;
      }

      if (data.limit_number_redemptions && data.max_redemptions) {
        payload.max_redemptions = data.max_redemptions;
      }

      if (data.expires_at) {
        payload.expires_at = Math.floor(new Date(data.expires_at).getTime() / 1000);
      }

      // Add verification configurations based on type
      if (data.verification_type === 'nft') {
        payload.nft_config = {
          addresses: data.nft_addresses?.filter((addr) => addr.trim()) || [],
          tags: data.nft_tags?.filter((tag) => tag.trim()) || [],
          trusted_issuers: data.trusted_issuers?.filter((issuer) => issuer.trim()) || [],
          trusted_parents: data.trusted_parents?.filter((parent) => parent.trim()) || [],
          min_balance: data.min_balance || 1,
        };
      } else if (data.verification_type === 'vc') {
        payload.vc_config = {
          roles: data.vc_roles?.filter((role) => role.trim()) || [],
          trusted_issuers: data.vc_trusted_issuers?.filter((issuer) => issuer.trim()) || [],
        };
      } else if (data.verification_type === 'user_restricted') {
        payload.customer_dids = data.customer_dids?.filter((did) => did.trim()) || [];
      }

      if (isEditing && promotionCode) {
        await api.put(`/api/promotion-codes/${promotionCode.id}`, payload);
        Toast.success(t('common.saved'));
        dispatch('promotion-code.updated');
      } else {
        await api.post('/api/promotion-codes', payload);
        Toast.success(t('admin.coupon.saved'));
        dispatch('promotion-code.created');
      }

      if (onSubmitCallback) {
        onSubmitCallback();
      }
      onClose();
    } catch (err) {
      console.error(err);
      Toast.error(formatError(err));
    }
  };

  const handleCancel = () => {
    reset();
    onClose();
  };

  const title = isEditing ? t('admin.promotionCode.edit') : t('admin.coupon.createPromotionCode');

  return (
    <Dialog
      open={open}
      disableEscapeKeyDown
      fullWidth
      maxWidth="sm"
      className="base-dialog"
      onClose={handleCancel}
      showCloseButton={false}
      title={title}
      actions={
        <Stack direction="row">
          <Button size="small" sx={{ mr: 2 }} onClick={handleCancel} disabled={isSubmitting}>
            {t('common.cancel')}
          </Button>
          <Button
            variant="contained"
            color="primary"
            size="small"
            disabled={isSubmitting}
            onClick={handleSubmit(onSubmit)}>
            {isSubmitting && <CircularProgress size={16} sx={{ mr: 1 }} />}
            {isEditing ? t('common.save') : t('admin.coupon.createPromotionCode')}
          </Button>
        </Stack>
      }>
      <FormProvider {...methods}>
        <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
          <Typography
            variant="body2"
            sx={{
              color: 'text.secondary',
            }}>
            {t('admin.coupon.promotionCodeDescription')}
          </Typography>

          <PromotionCodeForm showCodeInput showExpandedOptions availableCurrencies={availableCurrencies} />
        </Box>
      </FormProvider>
    </Dialog>
  );
}
