import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import {
  Box,
  TextField,
  FormControl,
  Select,
  MenuItem,
  FormControlLabel,
  Checkbox,
  Typography,
  Chip,
  Stack,
  InputAdornment,
  Button,
  Divider,
  Autocomplete,
  Avatar,
} from '@mui/material';
import { Controller, useFormContext, useWatch } from 'react-hook-form';
import { FormInput, FormLabel, api, getCustomerAvatar } from '@blocklet/payment-react';
import { useRequest } from 'ahooks';
import { useEffect } from 'react';
import CurrencyMultiSelect from './currency-multi-select';

export type PromotionCodeData = {
  code: string;
  description?: string;
  active: boolean;
  max_redemptions?: number;
  expires_at?: string;
  verification_type: 'code' | 'nft' | 'vc' | 'user_restricted';
  limit_number_redemptions?: boolean;
  add_expiration_date?: boolean;
  restrictions?: {
    first_time_transaction?: boolean;
    require_minimum_amount?: boolean;
    minimum_amount?: number;
    minimum_amount_currency?: string;
    currency_options?: Record<string, { minimum_amount: number }>;
  };
  customer_dids?: string[];
  nft_addresses?: string[];
  nft_tags?: string[];
  trusted_issuers?: string[];
  trusted_parents?: string[];
  min_balance?: number;
  vc_roles?: string[];
  vc_trusted_issuers?: string[];
};

export const DEFAULT_PROMOTION_CODE: PromotionCodeData = {
  code: '',
  description: '',
  active: true,
  verification_type: 'code',
  limit_number_redemptions: false,
  add_expiration_date: false,
  restrictions: {
    first_time_transaction: false,
    require_minimum_amount: false,
    currency_options: {},
  },
  customer_dids: [],
  nft_addresses: [],
  nft_tags: [],
  trusted_issuers: [],
  trusted_parents: [],
  min_balance: 1,
  vc_roles: [],
  vc_trusted_issuers: [],
};

type PromotionCodeFormProps = {
  prefix?: string;
  showCodeInput?: boolean;
  showExpandedOptions?: boolean;
  couponType?: 'percentage' | 'fixed_amount';
  availableCurrencies?: Array<{
    id: string;
    symbol: string;
    name: string;
  }>;
};

const fetchCustomers = (): Promise<{ list: any[]; count: number }> => {
  return api.get('/api/customers?limit=1000').then((res: any) => res.data);
};

export default function PromotionCodeForm({
  prefix = '',
  showCodeInput = false,
  showExpandedOptions = true,
  availableCurrencies = [],
}: Omit<PromotionCodeFormProps, 'couponType'>) {
  const { t } = useLocaleContext();
  const { control, setValue, watch } = useFormContext();

  const getFieldName = (name: string) => (prefix ? `${prefix}.${name}` : name);

  const { data: customersData } = useRequest(fetchCustomers);

  const watchVerificationType = useWatch({ control, name: getFieldName('verification_type') });
  const watchLimitNumberRedemptions = useWatch({ control, name: getFieldName('limit_number_redemptions') });
  const watchAddExpirationDate = useWatch({ control, name: getFieldName('add_expiration_date') });
  const watchRequireMinimumAmount = useWatch({ control, name: getFieldName('restrictions.require_minimum_amount') });
  const watchCurrencyOptions = useWatch({ control, name: getFieldName('restrictions.currency_options') });

  const customers = customersData?.list || [];

  // sync currency_options first currency to base fields
  useEffect(() => {
    if (watchRequireMinimumAmount && watchCurrencyOptions && typeof watchCurrencyOptions === 'object') {
      const currencyEntries = Object.entries(watchCurrencyOptions);
      if (currencyEntries.length > 0) {
        const firstEntry = currencyEntries[0];
        if (firstEntry) {
          const [firstCurrencyId, firstCurrencyData] = firstEntry;
          const amount = (firstCurrencyData as any).minimum_amount || 0;
          setValue(getFieldName('restrictions.minimum_amount'), amount, { shouldValidate: false });
          setValue(getFieldName('restrictions.minimum_amount_currency'), firstCurrencyId, { shouldValidate: false });
        }
      }
    } else if (!watchRequireMinimumAmount) {
      setValue(getFieldName('restrictions.minimum_amount'), undefined, { shouldValidate: false });
      setValue(getFieldName('restrictions.minimum_amount_currency'), undefined, { shouldValidate: false });
    }
  }, [watchRequireMinimumAmount, watchCurrencyOptions, setValue, getFieldName]);

  const generatePromotionCode = () => {
    return Math.random().toString(36).substring(2, 12).toUpperCase();
  };

  const getCustomerDisplayName = (customer: any) => {
    return customer.name || customer.email || customer.did || customer.id;
  };

  const handleArrayChange = (fieldName: string, value: string) => {
    const currentValue = watch(getFieldName(fieldName)) || [];
    if (value.trim()) {
      const newArray = [...currentValue, value.trim()];
      setValue(getFieldName(fieldName), newArray);
    }
  };

  const handleArrayRemove = (fieldName: string, index: number) => {
    const currentValue = watch(getFieldName(fieldName)) || [];
    const newArray = currentValue.filter((_: any, i: number) => i !== index);
    setValue(getFieldName(fieldName), newArray);
  };

  const renderArrayField = (fieldName: string, label: string, placeholder: string) => {
    const currentValue = watch(getFieldName(fieldName)) || [];

    return (
      <Box sx={{ position: 'relative' }}>
        <TextField
          label={label}
          placeholder={placeholder}
          fullWidth
          size="small"
          onKeyPress={(e) => {
            if (e.key === 'Enter') {
              e.preventDefault();
              const { value } = e.target as HTMLInputElement;
              handleArrayChange(fieldName, value);
              (e.target as HTMLInputElement).value = '';
            }
          }}
        />
        <Box
          sx={{
            position: 'absolute',
            top: 8,
            right: 12,
            fontSize: '0.75rem',
            color: 'text.secondary',
            pointerEvents: 'none',
            zIndex: 1,
          }}>
          Press Enter
        </Box>
        {currentValue.length > 0 && (
          <Stack direction="row" spacing={1} sx={{ mt: 1, flexWrap: 'wrap' }}>
            {currentValue.map((item: string, index: number) => (
              <Chip key={item} label={item} onDelete={() => handleArrayRemove(fieldName, index)} size="small" />
            ))}
          </Stack>
        )}
      </Box>
    );
  };

  const renderMultiCurrencyMinimumAmount = () => {
    return (
      <Box>
        <Typography
          variant="body2"
          sx={{
            color: 'text.secondary',
            mb: 2,
          }}>
          {t('admin.coupon.minimumAmountHelp')}
        </Typography>
        <CurrencyMultiSelect
          prefix={getFieldName('restrictions')}
          baseCurrencyFieldName="minimum_amount_currency"
          currencyOptionsFieldName="currency_options"
          unitAmountFieldName="minimum_amount"
          objectMode
          showBaseCurrency={false}
        />
      </Box>
    );
  };

  const renderCustomerSelection = () => {
    const currentValue = watch(getFieldName('customer_dids')) || [];
    const selectedOptions: (any | string)[] = [];

    customers.forEach((customer: any) => {
      if (currentValue.includes(customer.did) || currentValue.includes(customer.id)) {
        selectedOptions.push(customer);
      }
    });

    currentValue.forEach((did: string) => {
      if (!customers.some((c: any) => c.did === did || c.id === did)) {
        selectedOptions.push(did);
      }
    });

    return (
      <Box>
        <Autocomplete
          multiple
          options={customers}
          getOptionLabel={getCustomerDisplayName}
          value={selectedOptions}
          onChange={(_, newValue) => {
            const dids = newValue.map((item: any) => {
              if (typeof item === 'string') {
                return item;
              }
              return item.did || item.id;
            });
            setValue(getFieldName('customer_dids'), dids);
          }}
          freeSolo
          renderInput={(params) => (
            <TextField
              {...params}
              label={t('admin.coupon.customerDids')}
              placeholder={t('admin.coupon.customerDidsPlaceholder')}
              size="small"
              helperText={t('admin.coupon.customerDidsHelp')}
            />
          )}
          renderOption={(props, option) => (
            <Box component="li" {...props} sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
              <Avatar
                src={getCustomerAvatar(
                  option.did,
                  option?.updated_at ? new Date(option.updated_at).toISOString() : undefined
                )}
                sx={{ width: 24, height: 24 }}
                alt={getCustomerDisplayName(option)}
              />
              <Typography variant="body2">{getCustomerDisplayName(option)}</Typography>
            </Box>
          )}
          renderTags={(tagValues, getTagProps) =>
            tagValues.map((option, index) => {
              const isCustomer = typeof option === 'object';
              const displayLabel = isCustomer ? getCustomerDisplayName(option) : option;

              return (
                <Chip
                  variant="outlined"
                  label={displayLabel}
                  size="small"
                  color={isCustomer ? 'primary' : 'default'}
                  avatar={
                    isCustomer ? (
                      <Avatar
                        src={getCustomerAvatar(
                          option.did,
                          option?.updated_at ? new Date(option.updated_at).toISOString() : undefined
                        )}
                        sx={{ width: 20, height: 20 }}
                        alt={getCustomerDisplayName(option)}
                      />
                    ) : undefined
                  }
                  {...getTagProps({ index })}
                  key={isCustomer ? option.id : option}
                />
              );
            })
          }
          filterOptions={(options, params) => {
            const filtered = options.filter((option) =>
              getCustomerDisplayName(option).toLowerCase().includes(params.inputValue.toLowerCase())
            );

            const { inputValue } = params;
            const isExisting = options.some((option) => getCustomerDisplayName(option) === inputValue);
            if (inputValue !== '' && !isExisting && inputValue.length > 10) {
              filtered.push(inputValue as any);
            }

            return filtered;
          }}
        />
      </Box>
    );
  };

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
      {showCodeInput && (
        <Box sx={{ display: 'flex', gap: 2, alignItems: 'flex-end' }}>
          <FormInput
            name={getFieldName('code')}
            label={t('admin.coupon.codeOptional')}
            placeholder="FRIENDS20"
            helperText={t('admin.coupon.codeHelp')}
            InputProps={{
              endAdornment: (
                <InputAdornment position="end">
                  <Button
                    size="small"
                    onClick={() => {
                      setValue(getFieldName('code'), generatePromotionCode());
                    }}>
                    {t('admin.coupon.generate')}
                  </Button>
                </InputAdornment>
              ),
            }}
          />
        </Box>
      )}

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

      <FormControl component="fieldset" fullWidth>
        <FormLabel component="legend" sx={{ mb: 1, fontSize: '0.875rem', fontWeight: 500 }}>
          {t('admin.coupon.verificationType')}
        </FormLabel>
        <Controller
          name={getFieldName('verification_type')}
          control={control}
          render={({ field }) => (
            <Select {...field} size="small" displayEmpty>
              <MenuItem value="code">{t('admin.coupon.codeOnly')}</MenuItem>
              <MenuItem value="nft" disabled>
                {t('admin.coupon.nftVerification')}
              </MenuItem>
              <MenuItem value="vc" disabled>
                {t('admin.coupon.vcVerification')}
              </MenuItem>
              <MenuItem value="user_restricted">{t('admin.coupon.userWhitelist')}</MenuItem>
            </Select>
          )}
        />
      </FormControl>

      {watchVerificationType === 'nft' && (
        <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
          <Typography variant="h6">{t('admin.coupon.nftSettings')}</Typography>
          {renderArrayField('nft_addresses', t('admin.coupon.nftAddresses'), t('admin.coupon.nftAddressesPlaceholder'))}
          {renderArrayField('nft_tags', t('admin.coupon.nftTags'), t('admin.coupon.nftTagsPlaceholder'))}
          {renderArrayField(
            'trusted_issuers',
            t('admin.coupon.trustedIssuers'),
            t('admin.coupon.trustedIssuersPlaceholder')
          )}
          {renderArrayField(
            'trusted_parents',
            t('admin.coupon.trustedParents'),
            t('admin.coupon.trustedParentsPlaceholder')
          )}

          <FormInput
            name={getFieldName('min_balance')}
            label={t('admin.coupon.minBalance')}
            type="number"
            rules={{ min: 1 }}
          />
        </Box>
      )}

      {watchVerificationType === 'vc' && (
        <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
          <Typography variant="h6">{t('admin.coupon.vcSettings')}</Typography>
          {renderArrayField('vc_roles', t('admin.coupon.requiredRoles'), t('admin.coupon.requiredRolesPlaceholder'))}
          {renderArrayField(
            'vc_trusted_issuers',
            t('admin.coupon.trustedVcIssuers'),
            t('admin.coupon.trustedVcIssuersPlaceholder')
          )}
        </Box>
      )}

      {watchVerificationType === 'user_restricted' && (
        <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
          <Typography variant="h6">{t('admin.coupon.userWhitelistSettings')}</Typography>
          {renderCustomerSelection()}
        </Box>
      )}

      {showExpandedOptions && (
        <>
          <Divider />
          <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
            <Controller
              name={getFieldName('restrictions.first_time_transaction')}
              control={control}
              render={({ field }) => (
                <FormControlLabel
                  control={<Checkbox {...field} checked={field.value || false} />}
                  label={t('admin.coupon.eligibleFirstTime')}
                  sx={{
                    alignItems: 'flex-start',
                  }}
                />
              )}
            />

            <Controller
              name={getFieldName('limit_number_redemptions')}
              control={control}
              render={({ field }) => (
                <FormControlLabel
                  control={<Checkbox {...field} checked={field.value} />}
                  label={t('admin.coupon.limitNumberRedemptions')}
                  sx={{
                    alignItems: 'flex-start',
                  }}
                />
              )}
            />

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

            <Controller
              name={getFieldName('add_expiration_date')}
              control={control}
              render={({ field }) => (
                <FormControlLabel
                  control={<Checkbox {...field} checked={field.value} />}
                  label={t('admin.coupon.addExpirationDate')}
                  sx={{
                    alignItems: 'flex-start',
                  }}
                />
              )}
            />

            {watchAddExpirationDate && (
              <FormInput
                name={getFieldName('expires_at')}
                label={t('admin.coupon.expiresAt')}
                type="datetime-local"
                InputLabelProps={{ shrink: true }}
              />
            )}

            <Controller
              name={getFieldName('restrictions.require_minimum_amount')}
              control={control}
              render={({ field }) => (
                <FormControlLabel
                  control={
                    <Checkbox
                      {...field}
                      checked={field.value || false}
                      onChange={(e) => {
                        field.onChange(e.target.checked);
                        if (e.target.checked) {
                          const firstCurrency = availableCurrencies[0];
                          if (firstCurrency) {
                            setValue(
                              getFieldName('restrictions.currency_options'),
                              {
                                [firstCurrency.id]: { minimum_amount: 0 },
                              },
                              { shouldValidate: true }
                            );
                          }
                        } else {
                          setValue(getFieldName('restrictions.currency_options'), {}, { shouldValidate: true });
                        }
                      }}
                    />
                  }
                  label={t('admin.coupon.requireMinimumOrder')}
                  sx={{
                    alignItems: 'flex-start',
                  }}
                />
              )}
            />

            {watchRequireMinimumAmount && renderMultiCurrencyMinimumAmount()}
          </Box>
        </>
      )}
    </Box>
  );
}
