import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import Toast from '@arcblock/ux/lib/Toast';
import { api, formatError, usePaymentContext, FormInput, FormLabel, Collapse, Switch } from '@blocklet/payment-react';
import { AddOutlined } from '@mui/icons-material';
import {
  Button,
  Box,
  FormControl,
  Select,
  MenuItem,
  FormControlLabel,
  Checkbox,
  Typography,
  InputAdornment,
  Divider,
  IconButton,
} from '@mui/material';
import { useState, Fragment } from 'react';
import { FormProvider, useForm, Controller, useFieldArray } from 'react-hook-form';
import { cloneDeep } from 'lodash';
import useBus, { dispatch, EventAction } from 'use-bus';

import DrawerForm from '../../../../components/drawer-form';
import PromotionCodeForm, {
  DEFAULT_PROMOTION_CODE,
  PromotionCodeData,
} from '../../../../components/promotion/promotion-code-form';
import ProductDynamicSelect from '../../../../components/promotion/product-select';
import CurrencyMultiSelect from '../../../../components/promotion/currency-multi-select';
import { ProductsProvider, useProductsContext } from '../../../../contexts/products';
import CreateProduct from '../../../../components/product/create';

// Using PromotionCodeData from the imported component
type PromotionCode = PromotionCodeData;

type CouponFormData = {
  name: string;
  description?: string;
  id?: string;
  type: 'percentage' | 'fixed_amount';
  percent_off?: number;
  amount_off?: string;
  currency_id?: string;
  currency_options?: Array<{
    currency_id: string;
    amount_off: string;
    currency?: any;
  }>;
  duration: 'once' | 'forever' | 'repeating';
  duration_in_months?: number;
  applies_to_products: boolean;
  product_ids?: string[];
  limit_date_range: boolean;
  redeem_by?: string;
  limit_total_number: boolean;
  max_redemptions?: number;
  use_customer_facing_codes: boolean;
  promotion_codes: PromotionCode[];
};

type Props = {
  open?: boolean;
  onClose?: () => void;
  onSubmit?: () => void;
};

function CouponCreateContent({ onClose = () => {}, onSubmit: onSubmitCallback = () => {} }: Omit<Props, 'open'>) {
  const { t } = useLocaleContext();
  const { settings } = usePaymentContext();
  const { refresh } = useProductsContext();
  const [expandedSection, setExpandedSection] = useState<'configuration' | 'codes'>('configuration');
  const [createProductOpen, setCreateProductOpen] = useState(false);

  const methods = useForm<CouponFormData>({
    mode: 'onChange',
    defaultValues: {
      name: '',
      description: '',
      id: '',
      type: 'percentage',
      percent_off: 10,
      amount_off: '0',
      currency_id: settings.baseCurrency.id,
      currency_options: [],
      duration: 'once',
      duration_in_months: undefined,
      applies_to_products: false,
      product_ids: [],
      limit_date_range: false,
      redeem_by: '',
      limit_total_number: false,
      max_redemptions: undefined,
      use_customer_facing_codes: false,
      promotion_codes: [],
    },
  });

  const {
    control,
    handleSubmit,
    watch,
    formState: { errors },
  } = methods;

  const promotionCodes = useFieldArray({ control, name: 'promotion_codes' });

  // Handle product creation request
  useBus(
    (event: EventAction) => event.type === 'product.create.request',
    () => {
      setCreateProductOpen(true);
    }
  );

  const onProductCreated = () => {
    setCreateProductOpen(false);
    refresh();
  };

  const watchType = watch('type');
  const watchDuration = watch('duration');
  const watchUseCustomerFacingCodes = watch('use_customer_facing_codes');
  const watchLimitDateRange = watch('limit_date_range');
  const watchLimitTotalNumber = watch('limit_total_number');
  const watchCurrencyId = watch('currency_id');
  const watchCurrencyOptions = watch('currency_options') || [];

  const getAvailableCurrencies = () => {
    const allCurrencies = settings.paymentMethods?.flatMap((pm) => pm.payment_currencies) || [];

    if (watchType === 'fixed_amount') {
      const currencyIds = new Set<string>();
      if (watchCurrencyId) {
        currencyIds.add(watchCurrencyId);
      }

      watchCurrencyOptions.forEach((option: any) => {
        if (option.currency_id) {
          currencyIds.add(option.currency_id);
        }
      });

      return allCurrencies.filter((currency) => currencyIds.has(currency.id));
    }
    return allCurrencies;
  };

  const onSubmit = (data: CouponFormData) => {
    const payload: any = {
      name: data.name,
      duration: data.duration,
      metadata: {},
    };

    if (data.id) {
      payload.id = data.id;
    }

    if (data.description) {
      payload.description = data.description;
    }

    if (data.type === 'percentage') {
      payload.percent_off = data.percent_off;
    } else {
      // For fixed amount, handle base currency
      payload.amount_off = data.amount_off;
      payload.currency_id = data.currency_id;

      // Handle additional currencies - convert array to object format for backend
      if (data.currency_options && data.currency_options.length > 0) {
        payload.currency_options = {};
        data.currency_options.forEach((option) => {
          if (option.currency_id && option.amount_off) {
            payload.currency_options[option.currency_id] = {
              amount_off: parseFloat(option.amount_off) || 0,
            };
          }
        });
      }
    }

    // Only include duration_in_months when duration is 'repeating'
    if (data.duration === 'repeating') {
      payload.duration_in_months = data.duration_in_months || 1; // Default to 1 if not specified
    }

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

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

    if (data.applies_to_products && data.product_ids && data.product_ids.length > 0) {
      payload.applies_to = {
        products: data.product_ids,
      };
    }

    // Include promotion codes data directly in the coupon creation request
    if (data.use_customer_facing_codes && data.promotion_codes.length > 0) {
      payload.promotion_codes = data.promotion_codes.map((promoCode) => {
        const promoPayload: any = {
          active: promoCode.active,
          verification_type: promoCode.verification_type,
          max_redemptions: promoCode.limit_number_redemptions ? promoCode.max_redemptions : undefined,
          expires_at: promoCode.expires_at ? Math.floor(new Date(promoCode.expires_at).getTime() / 1000) : undefined,
          restrictions: {},
          metadata: {},
        };

        // Add description if provided
        if (promoCode.description) {
          promoPayload.description = promoCode.description;
        }

        // Include restrictions directly from promotion code data
        if (promoCode.restrictions) {
          promoPayload.restrictions = promoCode.restrictions;
        }

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

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

        return promoPayload;
      });
    }

    api
      .post('/api/coupons', payload)
      .then(() => {
        Toast.success(t('admin.coupon.saved'));
        dispatch('coupon.created');
        methods.reset();
        dispatch('drawer.submitted');
        if (onSubmitCallback) {
          onSubmitCallback();
        }
        if (onClose) {
          onClose();
        }
      })
      .catch((err: any) => {
        console.error(err);
        Toast.error(formatError(err));
      });
  };

  const handleFormSubmit = handleSubmit(onSubmit);

  return (
    <>
      <FormProvider {...methods}>
        <Box component="form" id="coupon-form" onSubmit={handleFormSubmit}>
          <Typography
            variant="body2"
            sx={{
              color: 'text.secondary',
              mb: 3,
            }}>
            {t('admin.coupon.description')}
          </Typography>

          <Collapse
            expanded={expandedSection === 'configuration'}
            value="configuration"
            card
            onChange={(_, expanded) => {
              if (expanded) {
                setExpandedSection('configuration');
              }
            }}
            trigger={t('admin.coupon.couponConfiguration')}>
            <Box sx={{ p: 2, display: 'flex', flexDirection: 'column', gap: 2 }}>
              <FormInput
                name="name"
                label={t('admin.coupon.name')}
                required
                placeholder="First purchase discount"
                helperText={errors?.name?.message || t('admin.coupon.nameHelp')}
                rules={{ required: t('common.required') }}
              />

              <FormInput
                name="description"
                label={t('admin.coupon.desc')}
                placeholder={t('admin.coupon.desc')}
                multiline
                minRows={2}
                maxRows={4}
                slotProps={{
                  htmlInput: {
                    maxLength: 500,
                  },
                }}
              />

              <FormInput name="id" label={t('admin.coupon.idOptional')} helperText={t('admin.coupon.idHelp')} />

              <Box>
                <FormLabel required>{t('admin.coupon.type')}</FormLabel>
                <Controller
                  name="type"
                  control={control}
                  render={({ field }) => (
                    <FormControl fullWidth size="small">
                      <Select {...field}>
                        <MenuItem value="percentage">{t('admin.coupon.percentageOff')}</MenuItem>
                        <MenuItem value="fixed_amount">{t('admin.coupon.fixedAmountOff')}</MenuItem>
                      </Select>
                    </FormControl>
                  )}
                />
              </Box>

              {watchType === 'percentage' ? (
                <FormInput
                  name="percent_off"
                  label={t('admin.coupon.percentageDiscount')}
                  type="number"
                  required
                  rules={{
                    min: 0,
                    max: 100,
                    validate: (v) => {
                      if (!v && v !== 0) {
                        return t('common.required');
                      }
                      if (Number(v) <= 0 || Number(v) > 100) {
                        return t('common.invalid');
                      }
                      return true;
                    },
                  }}
                  slotProps={{
                    input: {
                      endAdornment: <InputAdornment position="end">%</InputAdornment>,
                    },
                    htmlInput: {
                      min: 0,
                      max: 100,
                      precision: 2,
                    },
                  }}
                />
              ) : (
                <Box>
                  <FormLabel required>{t('admin.coupon.fixedAmount')}</FormLabel>
                  <CurrencyMultiSelect
                    baseCurrencyFieldName="currency_id"
                    currencyOptionsFieldName="currency_options"
                    unitAmountFieldName="amount_off"
                  />
                </Box>
              )}

              <Box sx={{ pl: 2 }}>
                <Controller
                  name="applies_to_products"
                  control={control}
                  render={({ field }) => (
                    <FormControlLabel
                      control={<Switch {...field} checked={field.value} />}
                      label={t('admin.coupon.applyToProducts')}
                      slotProps={{
                        typography: {
                          sx: {
                            marginLeft: '8px',
                          },
                        },
                      }}
                    />
                  )}
                />
              </Box>

              {watch('applies_to_products') && (
                <Box>
                  <FormLabel>{t('admin.coupon.selectProducts')}</FormLabel>
                  <Controller
                    name="product_ids"
                    control={control}
                    render={({ field }) => <ProductDynamicSelect value={field.value || []} onChange={field.onChange} />}
                  />
                </Box>
              )}

              <Box>
                <Controller
                  name="duration"
                  control={control}
                  render={({ field }) => (
                    <FormControl fullWidth size="small">
                      <FormLabel required>{t('admin.coupon.duration')}</FormLabel>
                      <Select {...field}>
                        <MenuItem value="once">{t('admin.coupon.once')}</MenuItem>
                        <MenuItem value="forever">{t('admin.coupon.forever')}</MenuItem>
                        <MenuItem value="repeating">{t('admin.coupon.repeating')}</MenuItem>
                      </Select>
                    </FormControl>
                  )}
                />
                <Typography
                  variant="body2"
                  sx={{
                    color: 'text.secondary',
                    mt: 1,
                  }}>
                  {t('admin.coupon.durationHelp')}
                </Typography>
              </Box>

              {watchDuration === 'repeating' && (
                <FormInput
                  name="duration_in_months"
                  label={t('admin.coupon.durationInMonths')}
                  type="number"
                  rules={{ required: 'Duration in months is required', min: 1 }}
                  slotProps={{
                    input: {
                      endAdornment: <InputAdornment position="end">{t('admin.coupon.months')}</InputAdornment>,
                    },
                  }}
                />
              )}

              <Divider />

              <Typography variant="h6">{t('admin.coupon.redemptionLimits')}</Typography>

              <Controller
                name="limit_date_range"
                control={control}
                render={({ field }) => (
                  <FormControlLabel
                    control={<Checkbox {...field} checked={field.value} />}
                    label={t('admin.coupon.limitDateRange')}
                  />
                )}
              />

              {watchLimitDateRange && (
                <FormInput name="redeem_by" label="" type="datetime-local" InputLabelProps={{ shrink: true }} />
              )}

              <Controller
                name="limit_total_number"
                control={control}
                render={({ field }) => (
                  <FormControlLabel
                    control={<Checkbox {...field} checked={field.value} />}
                    label={t('admin.coupon.limitTotalNumber')}
                  />
                )}
              />

              {watchLimitTotalNumber && (
                <FormInput
                  name="max_redemptions"
                  label={t('admin.coupon.maxRedemptions')}
                  type="number"
                  slotProps={{
                    input: {
                      endAdornment: <InputAdornment position="end">{t('admin.coupon.times')}</InputAdornment>,
                    },
                  }}
                />
              )}
            </Box>
          </Collapse>

          <Collapse
            expanded={expandedSection === 'codes'}
            value="codes"
            card
            onChange={(_, expanded) => {
              if (expanded) {
                setExpandedSection('codes');
              }
            }}
            trigger={t('admin.coupon.promotionCodes')}
            style={{
              marginTop: 2,
            }}>
            <Box sx={{ p: 2, display: 'flex', flexDirection: 'column', gap: 3 }}>
              <Controller
                name="use_customer_facing_codes"
                control={control}
                render={({ field }) => (
                  <FormControlLabel
                    control={<Checkbox {...field} checked={field.value} />}
                    label={t('admin.coupon.useCustomerFacingCodes')}
                  />
                )}
              />

              {watchUseCustomerFacingCodes && (
                <Box>
                  <Typography
                    variant="body2"
                    sx={{
                      color: 'text.secondary',
                      mb: 2,
                    }}>
                    {t('admin.coupon.codeHelp')}
                  </Typography>

                  {promotionCodes.fields.map((promoCode, index) => (
                    <Fragment key={promoCode.id}>
                      <Collapse
                        expanded
                        style={{ fontWeight: 'bold', width: '100%' }}
                        addons={
                          <IconButton size="small" onClick={() => promotionCodes.remove(index)} color="error">
                            <AddOutlined style={{ transform: 'rotate(45deg)' }} />
                          </IconButton>
                        }
                        trigger={`${t('admin.coupon.promotionCodes')} ${index + 1}: ${methods.watch(`promotion_codes.${index}.code`) || t('admin.coupon.newCode')}`}>
                        <Box sx={{ width: '100%', p: 1 }}>
                          <PromotionCodeForm
                            prefix={`promotion_codes.${index}`}
                            showCodeInput
                            showExpandedOptions
                            availableCurrencies={getAvailableCurrencies()}
                          />
                        </Box>
                      </Collapse>
                      <Divider sx={{ mt: 2, mb: 2 }} />
                    </Fragment>
                  ))}

                  <Button
                    variant="outlined"
                    color="primary"
                    sx={{
                      color: 'text.primary',
                      width: '100%',
                    }}
                    onClick={() => {
                      const newCode = cloneDeep(DEFAULT_PROMOTION_CODE);
                      promotionCodes.append(newCode);
                    }}>
                    <AddOutlined fontSize="small" /> {t('admin.coupon.addAnotherCode')}
                  </Button>
                </Box>
              )}

              {!watchUseCustomerFacingCodes && (
                <Typography
                  variant="body2"
                  sx={{
                    color: 'text.secondary',
                  }}>
                  {t('admin.coupon.promotionCodesHelp')}
                </Typography>
              )}
            </Box>
          </Collapse>
        </Box>
      </FormProvider>
      {createProductOpen && <CreateProduct onCancel={() => setCreateProductOpen(false)} onSave={onProductCreated} />}
    </>
  );
}

export default function CouponCreate({
  open = false,
  onClose = () => {},
  onSubmit: onSubmitCallback = () => {},
}: Props) {
  const { t } = useLocaleContext();

  return (
    <DrawerForm
      icon={<AddOutlined />}
      text={t('admin.coupon.create')}
      open={open}
      onClose={onClose}
      width={640}
      addons={
        <Button variant="contained" size="small" form="coupon-form" type="submit">
          {t('admin.coupon.create')}
        </Button>
      }>
      <ProductsProvider>
        <CouponCreateContent onClose={onClose} onSubmit={onSubmitCallback} />
      </ProductsProvider>
    </DrawerForm>
  );
}
