import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { usePaymentContext, findCurrency } from '@blocklet/payment-react';
import { Box, TextField, Stack, IconButton, InputAdornment } from '@mui/material';
import { DeleteOutlineOutlined } from '@mui/icons-material';
import { Controller, useFieldArray, useFormContext } from 'react-hook-form';
import CurrencySelect from '../price/currency-select';

type CurrencyMultiSelectProps = {
  prefix?: string;
  baseCurrencyFieldName?: string;
  currencyOptionsFieldName?: string;
  unitAmountFieldName?: string;
  objectMode?: boolean; // Support object format for currency_options
  showBaseCurrency?: boolean; // Whether to show the base currency field
  disabled?: boolean;
};

export default function CurrencyMultiSelect({
  prefix = '',
  baseCurrencyFieldName = 'currency_id',
  currencyOptionsFieldName = 'currency_options',
  unitAmountFieldName = 'amount_off',
  objectMode = false,
  showBaseCurrency = true,
  disabled = false,
}: CurrencyMultiSelectProps) {
  const { t } = useLocaleContext();
  const { settings } = usePaymentContext();
  const {
    control,
    setValue,
    watch,
    formState: { errors },
    trigger,
  } = useFormContext();

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

  const currencies = useFieldArray({
    control,
    name: getFieldName(currencyOptionsFieldName),
  });

  const baseCurrencyId = watch(getFieldName(baseCurrencyFieldName));
  const currencyOptionsObject = watch(getFieldName(currencyOptionsFieldName));

  // Object mode helpers
  const getObjectCurrencies = () => {
    if (!objectMode || !currencyOptionsObject || typeof currencyOptionsObject !== 'object') {
      return [];
    }
    return Object.entries(currencyOptionsObject).map(([currencyId, data]) => ({
      currency_id: currencyId,
      [unitAmountFieldName]: (data as any)[unitAmountFieldName] || 0,
    }));
  };

  const addObjectCurrency = (currencyId: string) => {
    const current = currencyOptionsObject || {};
    setValue(
      getFieldName(currencyOptionsFieldName),
      {
        ...current,
        [currencyId]: { [unitAmountFieldName]: 0 },
      },
      { shouldValidate: true }
    );
  };

  const removeObjectCurrency = (currencyId: string) => {
    const current = currencyOptionsObject || {};
    const updated = { ...current };
    delete updated[currencyId];
    setValue(getFieldName(currencyOptionsFieldName), updated, { shouldValidate: true });
  };

  const updateObjectCurrency = (oldCurrencyId: string, newCurrencyId: string) => {
    const current = currencyOptionsObject || {};
    const updated = { ...current };
    const data = updated[oldCurrencyId];
    delete updated[oldCurrencyId];
    updated[newCurrencyId] = data;
    setValue(getFieldName(currencyOptionsFieldName), updated, { shouldValidate: true });
  };

  // Use appropriate data source based on mode
  const currencyList = objectMode ? getObjectCurrencies() : currencies.fields;

  const getFieldError = (name: string) => {
    const names = name?.split('.');
    return names.reduce((prev, curr) => prev?.[curr], errors as any);
  };

  const validateAmount = (v: number) => {
    if (Number(v) <= 0) {
      return t('admin.price.unit_amount.positive');
    }
    return true;
  };

  const handleRemoveCurrency = async (indexOrCurrencyId: number | string) => {
    if (objectMode) {
      removeObjectCurrency(indexOrCurrencyId as string);
    } else {
      await currencies.remove(indexOrCurrencyId as number);
      trigger(getFieldName(baseCurrencyFieldName));
    }
  };

  const handleCurrencyChange = (indexOrOldCurrencyId: number | string, currencyId: string) => {
    if (objectMode) {
      updateObjectCurrency(indexOrOldCurrencyId as string, currencyId);
    } else {
      const index = indexOrOldCurrencyId as number;
      const update = {
        currency_id: currencyId,
      };
      // @ts-ignore
      if (currencies?.fields?.[index]?.currency) {
        // @ts-ignore
        update.currency = findCurrency(settings.paymentMethods, currencyId);
      }
      currencies.update(index, {
        ...currencies.fields[index],
        ...update,
      });
    }
  };

  const handleAddCurrency = (currencyId: string) => {
    if (objectMode) {
      addObjectCurrency(currencyId);
    } else {
      currencies.append({ currency_id: currencyId, [unitAmountFieldName.split('.').pop() || 'amount_off']: 0 });
    }
  };

  return (
    <Stack spacing={2} sx={{ width: '100%' }}>
      {/* Base Currency */}
      {showBaseCurrency && (
        <Box sx={{ width: '100%' }}>
          <Controller
            name={getFieldName(unitAmountFieldName)}
            control={control}
            rules={{
              required: t('admin.price.unit_amount.required'),
              validate: (v) => {
                return validateAmount(v);
              },
            }}
            disabled={disabled}
            render={({ field }) => (
              <TextField
                {...field}
                type="number"
                size="small"
                fullWidth
                disabled={disabled}
                error={!!getFieldError(getFieldName(unitAmountFieldName))}
                helperText={getFieldError(getFieldName(unitAmountFieldName))?.message}
                slotProps={{
                  input: {
                    endAdornment: (
                      <InputAdornment position="end">
                        <CurrencySelect
                          mode="selected"
                          hasSelected={(currency) =>
                            currencies.fields.some((x: any) => x.currency_id === currency.id) ||
                            currency.id === baseCurrencyId
                          }
                          currencyFilter={(c) => c.type !== 'credit'}
                          onSelect={(currencyId) => {
                            const index = currencies.fields.findIndex((x: any) => x.currency_id === baseCurrencyId);
                            if (index > -1) {
                              handleCurrencyChange(index, currencyId);
                            }
                            setValue(getFieldName('currency'), findCurrency(settings.paymentMethods, currencyId), {
                              shouldValidate: true,
                            });
                            setValue(getFieldName(baseCurrencyFieldName), currencyId, { shouldValidate: true });
                          }}
                          value={baseCurrencyId}
                          disabled={disabled}
                          selectSX={{ '.MuiOutlinedInput-notchedOutline': { border: 'none' } }}
                        />
                      </InputAdornment>
                    ),
                  },
                }}
                onChange={(e) => {
                  const { value } = e.target;
                  field.onChange(value);
                  if (objectMode) {
                    const current = currencyOptionsObject || {};
                    setValue(getFieldName(currencyOptionsFieldName), {
                      ...current,
                      [baseCurrencyId]: {
                        ...(current[baseCurrencyId] || {}),
                        [unitAmountFieldName]: value,
                      },
                    });
                  } else {
                    const index = currencies.fields.findIndex((x: any) => x.currency_id === baseCurrencyId);
                    if (index === -1) {
                      return;
                    }
                    setValue(
                      getFieldName(`${currencyOptionsFieldName}.${index}.${unitAmountFieldName.split('.').pop()}`),
                      value,
                      {
                        shouldValidate: true,
                      }
                    );
                  }
                }}
              />
            )}
          />
        </Box>
      )}

      {/* Additional Currencies */}
      {currencyList.filter((x: any) => !showBaseCurrency || x.currency_id !== baseCurrencyId).length > 0 && (
        <Stack spacing={1.5} sx={{ width: '100%' }}>
          {currencyList.map((item: any, index: number) => {
            if (showBaseCurrency && item.currency_id === baseCurrencyId) {
              return null;
            }
            const fieldName = objectMode
              ? getFieldName(`${currencyOptionsFieldName}.${item.currency_id}.${unitAmountFieldName}`)
              : getFieldName(`${currencyOptionsFieldName}.${index}.${unitAmountFieldName.split('.').pop()}`);
            const currency = findCurrency(settings.paymentMethods, item.currency_id);
            return (
              <Stack
                key={item.currency_id}
                direction="row"
                spacing={1}
                sx={{
                  alignItems: 'start',
                }}>
                <Box sx={{ flex: 1 }}>
                  <Controller
                    name={fieldName}
                    control={control}
                    rules={{
                      required: t('admin.price.unit_amount.required'),
                      validate: (v) => {
                        return validateAmount(v);
                      },
                    }}
                    disabled={disabled}
                    render={({ field }) => (
                      <TextField
                        {...field}
                        type="number"
                        size="small"
                        fullWidth
                        sx={{ minWidth: '300px' }}
                        disabled={disabled}
                        error={!!getFieldError(fieldName)}
                        helperText={getFieldError(fieldName)?.message as string}
                        onChange={(e) => {
                          const { value } = e.target;
                          field.onChange(value);
                          if (objectMode) {
                            const current = currencyOptionsObject || {};
                            setValue(
                              getFieldName(currencyOptionsFieldName),
                              {
                                ...current,
                                [item.currency_id]: {
                                  ...(current[item.currency_id] || {}),
                                  [unitAmountFieldName]: parseFloat(value) || 0,
                                },
                              },
                              { shouldValidate: true }
                            );
                            trigger(fieldName);
                          }
                        }}
                        slotProps={{
                          input: {
                            endAdornment: (
                              <InputAdornment position="end">
                                <CurrencySelect
                                  mode="selected"
                                  hasSelected={(c) =>
                                    currencyList.some((x: any) => x.currency_id === c.id) ||
                                    (showBaseCurrency && c.id === baseCurrencyId)
                                  }
                                  currencyFilter={(c) => c.type !== 'credit'}
                                  onSelect={(currencyId) => {
                                    if (objectMode) {
                                      handleCurrencyChange(item.currency_id, currencyId);
                                    } else {
                                      const cIndex = currencies.fields.findIndex(
                                        (x: any) => x.currency_id === currency?.id
                                      );
                                      if (cIndex > -1) {
                                        handleCurrencyChange(cIndex, currencyId);
                                      }
                                    }
                                  }}
                                  value={currency?.id!}
                                  disabled={disabled}
                                  selectSX={{ '.MuiOutlinedInput-notchedOutline': { border: 'none' } }}
                                />
                              </InputAdornment>
                            ),
                          },
                        }}
                      />
                    )}
                  />
                </Box>
                {!disabled && (
                  <IconButton
                    size="small"
                    disabled={disabled}
                    onClick={() => handleRemoveCurrency(objectMode ? item.currency_id : index)}
                    sx={{ mt: 0.5, ml: -1 }}>
                    <DeleteOutlineOutlined color="error" sx={{ opacity: 0.75 }} />
                  </IconButton>
                )}
              </Stack>
            );
          })}
        </Stack>
      )}

      {/* Add more currencies */}
      {!disabled && (
        <Box sx={{ width: '100%' }}>
          <CurrencySelect
            mode="waiting"
            hasSelected={(currency) =>
              currencyList.some((x: any) => x.currency_id === currency.id) ||
              (showBaseCurrency && currency.id === baseCurrencyId)
            }
            currencyFilter={(c) => c.type !== 'credit'}
            onSelect={handleAddCurrency}
            value=""
            width="100%"
          />
        </Box>
      )}
    </Stack>
  );
}
