import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { api, dayjs, formatAmount, formatTime } from '@blocklet/payment-react';
import type { TPaymentCurrency, TSubscriptionExpanded } from '@blocklet/payment-types';
import { Box, Divider, FormControlLabel, Radio, RadioGroup, Stack, TextField, Typography, styled } from '@mui/material';
import { useRequest } from 'ahooks';
import { useEffect, useMemo } from 'react';
import { Controller, useFormContext, useWatch } from 'react-hook-form';

const fetchData = (
  id: string,
  time: string
): Promise<{ total: string; unused: string; paymentCurrency: TPaymentCurrency }> => {
  return api.get(`/api/subscriptions/${id}/proration?time=${encodeURIComponent(time)}`).then((res: any) => res.data);
};

const fetchStakingData = (id: string, time: string): Promise<{ return_amount: string; slash_amount: string }> => {
  return api.get(`/api/subscriptions/${id}/staking?time=${encodeURIComponent(time)}`).then((res: any) => res.data);
};

export default function SubscriptionCancelForm({ data }: { data: TSubscriptionExpanded }) {
  const { t } = useLocaleContext();
  const { control, setValue, formState } = useFormContext();
  const cancelAt = useWatch({ control, name: 'cancel.at' });
  const cancelTime = useWatch({ control, name: 'cancel.time' });
  const refundType = useWatch({ control, name: 'cancel.refund' });
  const stakingType = useWatch({ control, name: 'cancel.staking' });
  const actualCancelAt = useMemo(() => {
    if (cancelAt === 'custom') {
      return cancelTime;
    }
    if (cancelAt === 'current_period_end') {
      return new Date(data.current_period_end * 1000);
    }
    return '';
  }, [cancelAt, cancelTime]);
  const { loading, data: refund, refresh } = useRequest(() => fetchData(data.id, actualCancelAt));

  const { data: staking } = useRequest(() => {
    if (data.paymentMethod?.type === 'arcblock') {
      return fetchStakingData(data.id, actualCancelAt);
    }
    return Promise.resolve({ return_amount: '0', slash_amount: '0' });
  });
  useEffect(() => {
    if (data) {
      refresh();
    }
    if (cancelAt === 'current_period_end') {
      setValue('cancel.refund', 'none');
    }
  }, [cancelAt, cancelTime]); // eslint-disable-line
  const stakingDisabled = !staking || staking?.return_amount === '0';
  const refundDisabled = !refund || refund.total === '0';
  const isCustom = cancelAt === 'custom';
  const { decimal, symbol } = data.paymentCurrency;

  return (
    <Root
      sx={{
        width: {
          xs: '100%',
          sm: 450,
        },
      }}>
      <Stack
        direction="row"
        spacing={3}
        sx={{
          alignItems: 'flex-start',
        }}>
        <Typography className="form-title">{t('admin.subscription.cancel.at.title')}</Typography>
        <Stack>
          <RadioGroup>
            <FormControlLabel
              value="now"
              onClick={() => setValue('cancel.at', 'now')}
              control={<Radio checked={cancelAt === 'now'} />}
              label={t('admin.subscription.cancel.at.now', { date: formatTime(new Date()) })}
            />
            <FormControlLabel
              value="current_period_end"
              onClick={() => setValue('cancel.at', 'current_period_end')}
              control={<Radio checked={cancelAt === 'current_period_end'} />}
              label={t('admin.subscription.cancel.at.current_period_end', {
                date: formatTime(new Date(data.current_period_end * 1000)),
              })}
            />
            <FormControlLabel
              value="custom"
              onClick={() => setValue('cancel.at', 'custom')}
              control={<Radio checked={cancelAt === 'custom'} />}
              label={t('admin.subscription.cancel.at.custom')}
            />
          </RadioGroup>
          {isCustom && (
            <Controller
              name="cancel.time"
              rules={{
                required: isCustom,
                validate: (value) => {
                  const now = dayjs();
                  const selectedTime = dayjs(value);
                  const periodEndTime = dayjs.unix(data.current_period_end);
                  if (selectedTime.isBefore(now) || selectedTime.isAfter(periodEndTime)) {
                    return t('admin.subscription.cancel.at.timeError');
                  }
                  return true;
                },
              }}
              control={control}
              render={({ field }) => (
                <TextField
                  size="small"
                  variant="outlined"
                  type="datetime-local"
                  {...field}
                  // @ts-ignore
                  error={!!formState.errors.cancel?.time}
                  // @ts-ignore
                  helperText={formState.errors.cancel?.time?.message as string}
                />
              )}
            />
          )}
        </Stack>
      </Stack>
      <Divider sx={{ my: 1 }} />
      <Stack
        direction="row"
        spacing={3}
        sx={{
          alignItems: 'flex-start',
        }}>
        <Typography className="form-title">{t('admin.subscription.cancel.refund.title')}</Typography>
        <Stack>
          <RadioGroup>
            <FormControlLabel
              value="none"
              disabled={loading || refundDisabled}
              onClick={() => !(loading || refundDisabled) && setValue('cancel.refund', 'none')}
              control={<Radio checked={refundType === 'none'} />}
              label={t('admin.subscription.cancel.refund.none')}
            />
            <FormControlLabel
              value="last"
              disabled={loading || refundDisabled}
              onClick={() => !(loading || refundDisabled) && setValue('cancel.refund', 'last')}
              control={<Radio checked={refundType === 'last'} />}
              label={t('admin.subscription.cancel.refund.last', {
                symbol: refund?.paymentCurrency?.symbol || symbol,
                total: formatAmount(refund?.total || '0', refund?.paymentCurrency?.decimal || decimal),
              })}
            />
            <FormControlLabel
              value="proration"
              disabled={loading || refundDisabled}
              onClick={() => !(loading || refundDisabled) && setValue('cancel.refund', 'proration')}
              control={<Radio checked={refundType === 'proration'} />}
              label={t('admin.subscription.cancel.refund.proration', {
                symbol: refund?.paymentCurrency?.symbol || symbol,
                total: formatAmount(refund?.total || '0', refund?.paymentCurrency?.decimal || decimal),
                unused: formatAmount(refund?.unused || '0', refund?.paymentCurrency?.decimal || decimal),
              })}
            />
          </RadioGroup>
        </Stack>
      </Stack>
      {data.paymentMethod.type === 'arcblock' && (
        <>
          <Divider sx={{ my: 1 }} />
          <Stack
            direction="row"
            spacing={3}
            sx={{
              alignItems: 'flex-start',
            }}>
            <Typography className="form-title">{t('admin.subscription.cancel.staking.title')}</Typography>
            <RadioGroup>
              <FormControlLabel
                value="none"
                disabled={loading || stakingDisabled}
                onClick={() => !(loading || stakingDisabled) && setValue('cancel.staking', 'none')}
                control={<Radio checked={stakingType === 'none'} />}
                label={t('admin.subscription.cancel.staking.none')}
              />
              <FormControlLabel
                value="proration"
                disabled={loading || stakingDisabled}
                onClick={() => !(loading || stakingDisabled) && setValue('cancel.staking', 'proration')}
                control={<Radio checked={stakingType === 'proration'} />}
                label={t('admin.subscription.cancel.staking.proration', {
                  unused: formatAmount(staking?.return_amount || '0', decimal),
                  symbol,
                })}
              />
              <FormControlLabel
                value="slash"
                disabled={loading || stakingDisabled}
                onClick={() => !(loading || stakingDisabled) && setValue('cancel.staking', 'slash')}
                control={<Radio checked={stakingType === 'slash'} />}
                label={t('admin.subscription.cancel.staking.slash', {
                  unused: formatAmount(staking?.slash_amount || '0', decimal),
                  symbol,
                })}
              />
            </RadioGroup>
          </Stack>
          {stakingType === 'slash' && (
            <Controller
              name="cancel.slashReason"
              control={control}
              rules={{
                required: t('common.required'),
                validate: (value) => value.trim() !== '' || t('common.required'),
              }}
              render={({ field }) => (
                <TextField
                  {...field}
                  variant="outlined"
                  size="small"
                  fullWidth
                  multiline
                  minRows={2}
                  maxRows={4}
                  placeholder={t('admin.subscription.cancel.staking.slashReason')}
                  error={!!(formState.errors as any)?.cancel?.slashReason}
                  helperText={(formState.errors as any)?.cancel?.slashReason?.message}
                  slotProps={{
                    htmlInput: {
                      maxLength: 200,
                    },
                  }}
                />
              )}
            />
          )}
        </>
      )}
      <Divider sx={{ my: 1 }} />
      <Stack
        direction="row"
        spacing={3}
        sx={{
          alignItems: 'flex-start',
        }}>
        <Typography className="form-title">{t('admin.subscription.cancel.comment.title')}</Typography>
        <Controller
          name="cancel.comment"
          control={control}
          rules={{
            required: t('common.required'),
            validate: (value) => value.trim() !== '' || t('common.required'),
          }}
          render={({ field }) => (
            <TextField
              {...field}
              variant="outlined"
              size="small"
              fullWidth
              multiline
              minRows={2}
              maxRows={4}
              placeholder={t('admin.subscription.cancel.comment.placeholder')}
              error={!!(formState.errors as any)?.cancel?.comment}
              helperText={(formState.errors as any)?.cancel?.comment?.message}
              slotProps={{
                htmlInput: {
                  maxLength: 200,
                },
              }}
            />
          )}
        />
      </Stack>
    </Root>
  );
}

const Root = styled(Box)`
  .form-title {
    width: 60px;
    height: 39px;
    display: flex;
    align-items: center;
  }
`;
