import React, { useState, useEffect, useRef } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import Toast from '@arcblock/ux/lib/Toast';
import {
  Box,
  Typography,
  TextField,
  Button,
  CircularProgress,
  Alert,
  Stack,
  Divider,
  Card,
  CardActionArea,
  Grid,
} from '@mui/material';
import { styled } from '@mui/system';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import {
  usePaymentContext,
  getPrefix,
  formatError,
  formatAmountPrecisionLimit,
  formatTime,
  api,
  formatBNStr,
  getTokenBalanceLink,
} from '@blocklet/payment-react';
import { joinURL } from 'ufo';
import type { TSubscriptionExpanded } from '@blocklet/payment-types';
import { AccountBalanceWalletOutlined, ArrowBackOutlined, ArrowForwardOutlined } from '@mui/icons-material';
import { BN, fromUnitToToken } from '@ocap/util';
import RechargeList from '../../../components/invoice/recharge';
import SubscriptionDescription from '../../../components/subscription/description';
import InfoRow from '../../../components/info-row';
import Currency from '../../../components/currency';
import SubscriptionMetrics from '../../../components/subscription/metrics';
import { goBackOrFallback, MAX_SAFE_AMOUNT } from '../../../libs/util';
import CustomerLink from '../../../components/customer/link';
import { useSessionContext } from '../../../contexts/session';
import { formatSmartDuration, TimeUnit } from '../../../libs/dayjs';
import { useArcsphere } from '../../../hooks/browser';

const Root = styled(Stack)(({ theme }) => ({
  marginBottom: theme.spacing(3),
  gap: theme.spacing(3),
  flexDirection: 'column',
  margin: '0 auto',
}));

const BalanceCard = styled(Box)(({ theme }) => ({
  padding: theme.spacing(2),
  backgroundColor: theme.palette.background.paper,
  border: `1px solid ${theme.palette.divider}`,
  borderRadius: theme.shape.borderRadius,
  marginBottom: theme.spacing(2),
}));

export default function RechargePage() {
  const { t, locale } = useLocaleContext();
  const { id: subscriptionId } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const { connect } = usePaymentContext();
  const inArcsphere = useArcsphere();
  const [subscription, setSubscription] = useState<TSubscriptionExpanded | null>(null);
  const [amount, setAmount] = useState('');
  const [amountError, setAmountError] = useState('');
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const customInputRef = useRef<HTMLInputElement>(null);
  const [payerValue, setPayerValue] = useState<{
    paymentAddress: string;
    token: string;
  } | null>(null);
  const [customAmount, setCustomAmount] = useState(false);
  const [presetAmounts, setPresetAmounts] = useState<Array<{ amount: string; cycles: number }>>([]);
  const { session } = useSessionContext();
  const [cycleAmount, setCycleAmount] = useState('0');

  const {
    paymentCurrency,
    payment_details: paymentDetails,
    payment_settings: paymentSettings,
    paymentMethod,
  } = subscription || {
    customer: null,
    paymentCurrency: null,
    payment_details: null,
    paymentMethod: null,
    payment_settings: null,
  };

  const receiveAddress =
    // @ts-ignore
    paymentDetails?.[paymentMethod?.type]?.payer ||
    // @ts-ignore
    paymentSettings?.payment_method_options?.[paymentMethod?.type]?.payer;
  const fetchData = async () => {
    try {
      setLoading(true);
      const [subscriptionRes, payerTokenRes, upcomingRes] = await Promise.all([
        api.get(`/api/subscriptions/${subscriptionId}`),
        api.get(`/api/subscriptions/${subscriptionId}/payer-token`),
        api.get(`/api/subscriptions/${subscriptionId}/cycle-amount`),
      ]);
      setSubscription(subscriptionRes.data);
      setPayerValue(payerTokenRes.data);

      // Calculate preset amounts
      const getCycleAmount = (cycles: number) =>
        fromUnitToToken(
          new BN(upcomingRes.data.amount).mul(new BN(cycles)).toString(),
          upcomingRes.data?.currency?.decimal
        );
      setPresetAmounts([
        { amount: getCycleAmount(1), cycles: 1 },
        { amount: getCycleAmount(2), cycles: 2 },
        { amount: getCycleAmount(3), cycles: 3 },
        { amount: getCycleAmount(5), cycles: 5 },
        { amount: getCycleAmount(10), cycles: 10 },
      ]);

      setCycleAmount(fromUnitToToken(upcomingRes.data.amount || '0', upcomingRes.data?.currency?.decimal) || '0');
      if (!amount && !customAmount) {
        handleSelect(getCycleAmount(10));
      }
    } catch (err) {
      setError(formatError(err) || t('common.fetchError'));
      console.error(err);
    } finally {
      setLoading(false);
    }
  };

  const rechargeRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    fetchData();
  }, [subscriptionId]);

  useEffect(() => {
    if (rechargeRef.current && subscription) {
      setTimeout(() => {
        // @ts-ignore
        const rechargePosition = rechargeRef.current.getBoundingClientRect();
        const absoluteTop = window.scrollY + rechargePosition.top;
        const scrollToPosition = absoluteTop - 20;

        window.scrollTo({
          top: scrollToPosition,
          behavior: 'smooth',
        });
      }, 200);
    }
  }, [subscription]);

  const handleRecharge = () => {
    if (!subscription) return;

    if (Number.isNaN(Number(amount))) {
      return;
    }

    connect.open({
      containerEl: undefined as unknown as Element,
      saveConnect: false,
      action: 'recharge',
      locale: locale as 'en' | 'zh',
      prefix: joinURL(getPrefix(), '/api/did'),
      extraParams: { subscriptionId, amount: Number(amount) },
      messages: {
        scan: t('common.connect.defaultScan'),
        title: t('customer.recharge.title'),
        confirm: t('common.connect.confirm'),
      } as any,
      onSuccess: () => {
        connect.close();
        Toast.success(t('customer.recharge.success'));
        fetchData();
      },
      onClose: () => {
        connect.close();
      },
      onError: (err: any) => {
        Toast.error(formatError(err));
      },
    });
  };

  const handleAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { value } = e.target;
    if (!subscription) return;
    if (!/^\d*\.?\d*$/.test(value)) return;
    // 不允许以小数点开头
    if (value.startsWith('.')) return;
    if (Number(value) > MAX_SAFE_AMOUNT) {
      return;
    }
    const precision = subscription.paymentCurrency.maximum_precision || 6;
    const errorMessage = formatAmountPrecisionLimit(value, locale, precision);
    setAmountError(errorMessage || '');
    setAmount(value);
  };

  const handleSelect = (selectedAmount: string) => {
    setAmount(selectedAmount);
    setCustomAmount(false);
  };

  const handleCustomSelect = () => {
    setCustomAmount(true);
    setAmount('');
    setTimeout(() => {
      customInputRef.current?.focus();
    }, 0);
  };

  if (loading) {
    return <CircularProgress />;
  }

  if (error) {
    return <Alert severity="error">{error}</Alert>;
  }

  if (!subscription) {
    return <Alert severity="info">{t('common.dataNotFound')}</Alert>;
  }

  if (subscription?.customer?.did && session?.user?.did && subscription.customer.did !== session.user.did) {
    return <Alert severity="error">{t('common.accessDenied')}</Alert>;
  }
  const currentBalance = formatBNStr(payerValue?.token || '0', paymentCurrency?.decimal, 6, false);

  const supportRecharge = ['arcblock', 'ethereum', 'base'].includes(paymentMethod?.type || '');

  const formatEstimatedDuration = (cycles: number) => {
    const { interval, interval_count: intervalCount } = subscription.pending_invoice_item_interval;
    const totalIntervals = cycles * intervalCount;
    const availableUnitKeys = ['hour', 'day', 'week', 'month', 'year'];

    if (!availableUnitKeys.includes(interval)) {
      return t('customer.recharge.estimatedDuration', {
        duration: totalIntervals,
        unit: t('customer.recharge.intervals').toLowerCase(),
      });
    }
    return t('common.estimatedDuration', {
      duration: formatSmartDuration(totalIntervals, interval as TimeUnit, {
        t,
      }),
    });
  };

  const balanceLink = getTokenBalanceLink(paymentMethod!, payerValue?.paymentAddress || receiveAddress);

  return (
    <Root>
      <Stack
        direction="row"
        sx={{
          justifyContent: 'space-between',
          alignItems: 'center',
          position: 'relative',
        }}>
        {!inArcsphere ? (
          <Stack
            direction="row"
            onClick={() => goBackOrFallback('/customer')}
            sx={{
              alignItems: 'center',
              fontWeight: 'normal',
              cursor: 'pointer',
            }}>
            <ArrowBackOutlined fontSize="small" sx={{ mr: 0.5, color: 'text.secondary' }} />
            <Typography variant="h6" sx={{ color: 'text.secondary', fontWeight: 'normal' }}>
              {t('common.previous')}
            </Typography>
          </Stack>
        ) : (
          <Box />
        )}
        <Button variant="outlined" onClick={() => navigate(`/customer/subscription/${subscriptionId}`)}>
          {t('customer.recharge.view')}
        </Button>
      </Stack>
      <Box>
        <Box
          sx={{
            display: 'flex',
            gap: { xs: 2, sm: 2, md: 5 },
            flexWrap: 'wrap',
            flexDirection: { xs: 'column', sm: 'column', md: 'row' },
            alignItems: { xs: 'flex-start', sm: 'flex-start', md: 'center' },
          }}>
          <Stack
            direction="row"
            sx={{
              justifyContent: 'space-between',
              alignItems: 'center',
            }}>
            <Stack
              direction="row"
              sx={{
                alignItems: 'center',
                flexWrap: 'wrap',
                gap: 1,
              }}>
              <SubscriptionDescription subscription={subscription} variant="h1" />
            </Stack>
          </Stack>
          <Stack
            sx={{
              justifyContent: 'flex-start',
              flexWrap: 'wrap',
              flexDirection: { xs: 'column', sm: 'column', md: 'row' },
              alignItems: { xs: 'flex-start', sm: 'flex-start', md: 'center' },
              gap: { xs: 1, sm: 1, md: 3 },
            }}>
            <SubscriptionMetrics subscription={subscription} showBalance={false} />
          </Stack>
        </Box>

        <Divider sx={{ my: 2 }} />

        <Box
          sx={{
            display: 'grid',
            gridTemplateColumns: { xs: 'repeat(1, 1fr)', sm: 'repeat(1, 1fr)', md: 'repeat(1, 1fr)' },
            gap: { xs: 0, md: 2 },
            '.currency-name': {
              color: 'text.secondary',
            },
            '.info-row-label': {
              fontWeight: 500,
            },
          }}>
          <InfoRow
            label={t('common.customer')}
            value={<CustomerLink customer={subscription?.customer} linked={false} />}
            direction="column"
            alignItems="flex-start"
          />
          <InfoRow
            label={t('admin.subscription.currentPeriod')}
            value={`${formatTime(subscription.current_period_start * 1000)} ~ ${formatTime(subscription.current_period_end * 1000)}`}
            direction="column"
            alignItems="flex-start"
          />
          <InfoRow
            label={t('admin.paymentMethod._name')}
            value={<Currency logo={subscription.paymentMethod?.logo} name={subscription.paymentMethod?.name} />}
            direction="column"
            alignItems="flex-start"
          />
          <InfoRow
            label={t('admin.paymentCurrency.name')}
            value={
              <Stack direction="row" spacing={2}>
                <Currency logo={subscription.paymentCurrency.logo} name={subscription.paymentCurrency.symbol} />
              </Stack>
            }
            direction="column"
            alignItems="flex-start"
          />
        </Box>
      </Box>
      <Divider />
      <Box sx={{ maxWidth: 600 }} ref={rechargeRef}>
        <Typography variant="h4" gutterBottom>
          {t('customer.recharge.title')}
        </Typography>

        {supportRecharge ? (
          <>
            <BalanceCard>
              <Typography variant="subtitle1">{t('customer.recharge.receiveAddress')}</Typography>
              <Typography variant="h4" sx={{ wordBreak: 'break-all' }}>
                {payerValue?.paymentAddress || receiveAddress}
              </Typography>
            </BalanceCard>

            <BalanceCard
              onClick={() => balanceLink && window.open(balanceLink, '_blank')}
              sx={{
                color: 'text.primary',
                borderRadius: 1,
                transition: 'all 0.2s ease-in-out',
                cursor: balanceLink ? 'pointer' : 'default',
                position: 'relative',
                '&:hover': balanceLink
                  ? {
                      '& .MuiSvgIcon-root': {
                        opacity: 1,
                        transform: 'translateX(0)',
                      },
                    }
                  : undefined,
              }}>
              <Stack
                direction="row"
                spacing={1}
                sx={{
                  alignItems: 'center',
                }}>
                <Stack
                  sx={{
                    flex: 1,
                  }}>
                  <Typography
                    variant="body1"
                    color="inherit"
                    sx={{ display: 'flex', alignItems: 'center', gap: 1, color: 'text.secondary' }}>
                    <AccountBalanceWalletOutlined color="success" fontSize="small" />
                    {t('admin.customer.summary.balance')}
                  </Typography>
                  <Typography variant="h3" sx={{ fontWeight: 'bold', mt: 1, color: 'text.primary' }}>
                    {currentBalance} {subscription.paymentCurrency.symbol}
                  </Typography>
                </Stack>
                {balanceLink && (
                  <ArrowForwardOutlined
                    sx={{
                      opacity: 0,
                      transform: 'translateX(-10px)',
                      transition: 'all 0.2s ease-in-out',
                      color: 'inherit',
                    }}
                  />
                )}
              </Stack>
            </BalanceCard>

            <Stack sx={{ mb: 2, mt: 2, backgroundColor: 'background.default' }}>
              <Grid container spacing={2}>
                {presetAmounts.map(({ amount: presetAmount, cycles }) => (
                  <Grid
                    key={presetAmount}
                    size={{
                      xs: 6,
                      sm: 4,
                    }}>
                    <Card
                      variant="outlined"
                      sx={{
                        height: '100%',
                        display: 'flex',
                        flexDirection: 'column',
                        justifyContent: 'center',
                        transition: 'all 0.3s',
                        cursor: 'pointer',
                        '&:hover': {
                          transform: 'translateY(-4px)',
                          boxShadow: 3,
                        },
                        ...(amount === presetAmount && !customAmount
                          ? { borderColor: 'primary.main', borderWidth: 1 }
                          : {}),
                      }}>
                      <CardActionArea onClick={() => handleSelect(presetAmount)} sx={{ height: '100%' }}>
                        <Stack
                          direction="column"
                          spacing={1}
                          sx={{
                            alignItems: 'center',
                            justifyContent: 'center',
                            p: 1,
                          }}>
                          <Typography
                            variant="h6"
                            sx={{
                              fontWeight: 600,
                              color: amount === presetAmount && !customAmount ? 'primary.main' : 'text.primary',
                            }}>
                            {presetAmount} {subscription.paymentCurrency.symbol}
                          </Typography>
                          <Typography
                            variant="caption"
                            sx={{
                              color: 'text.secondary',
                            }}>
                            {formatEstimatedDuration(cycles)}
                          </Typography>
                        </Stack>
                      </CardActionArea>
                    </Card>
                  </Grid>
                ))}
                <Grid
                  size={{
                    xs: 6,
                    sm: 4,
                  }}>
                  <Card
                    variant="outlined"
                    sx={{
                      height: '100%',
                      display: 'flex',
                      flexDirection: 'column',
                      justifyContent: 'center',
                      transition: 'all 0.3s',
                      cursor: 'pointer',
                      '&:hover': {
                        transform: 'translateY(-4px)',
                        boxShadow: 3,
                      },
                      ...(customAmount ? { borderColor: 'primary.main', borderWidth: 1 } : {}),
                    }}>
                    <CardActionArea onClick={handleCustomSelect} sx={{ height: '100%' }}>
                      <Stack
                        direction="column"
                        spacing={1}
                        sx={{
                          alignItems: 'center',
                          justifyContent: 'center',
                          p: 1,
                        }}>
                        <Typography
                          variant="h6"
                          sx={{ fontWeight: 600, color: customAmount ? 'primary.main' : 'text.primary' }}>
                          {t('customer.recharge.custom')}
                        </Typography>
                      </Stack>
                    </CardActionArea>
                  </Card>
                </Grid>
              </Grid>
            </Stack>

            {customAmount && (
              <Box>
                <TextField
                  fullWidth
                  label={t('customer.recharge.amount')}
                  variant="outlined"
                  type="text"
                  value={amount}
                  error={!!amountError}
                  helperText={amountError}
                  onChange={handleAmountChange}
                  sx={{ mt: 1 }}
                  inputRef={customInputRef}
                  slotProps={{
                    input: {
                      endAdornment: <Typography>{subscription.paymentCurrency.symbol}</Typography>,
                    },
                    htmlInput: {
                      min: 0,
                      max: MAX_SAFE_AMOUNT,
                      autoComplete: 'off',
                    },
                  }}
                />
                {amount && Number(amount) > 0 && Number(cycleAmount) > 0 && !amountError && (
                  <Typography
                    variant="body2"
                    sx={{
                      fontSize: 12,
                      color: 'text.lighter',
                      mt: '8px !important',
                    }}>
                    {formatEstimatedDuration(
                      Math.floor(Number(amount) / Number(cycleAmount)) < 1
                        ? parseFloat((Number(amount) / Number(cycleAmount)).toFixed(1))
                        : Math.floor(Number(amount) / Number(cycleAmount))
                    )}
                  </Typography>
                )}
              </Box>
            )}

            <Button
              fullWidth
              size="large"
              variant="contained"
              color="primary"
              onClick={handleRecharge}
              sx={{ mt: 2 }}
              disabled={!amount || parseFloat(amount) <= 0 || !!amountError}>
              {t('customer.recharge.submit')}
            </Button>
          </>
        ) : (
          <Alert severity="info">{t('customer.recharge.unsupported')}</Alert>
        )}
      </Box>
      <Divider />
      <Typography variant="h4" gutterBottom>
        {t('customer.recharge.history')}
      </Typography>
      <RechargeList subscription_id={subscriptionId} currency_id={paymentCurrency?.id} />
    </Root>
  );
}
