import { useState } from 'react';
import { Button, Typography, Stack, Alert } from '@mui/material';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import Toast from '@arcblock/ux/lib/Toast';
import { joinURL } from 'ufo';
import type { Subscription, TSubscriptionExpanded } from '@blocklet/payment-types';
import { useRequest } from 'ahooks';
import Dialog from '@arcblock/ux/lib/Dialog/dialog';
import { usePaymentContext } from '../contexts/payment';
import { formatError, formatToDate, getPrefix, isCrossOrigin } from '../libs/util';
import api from '../libs/api';
import LoadingButton from './loading-button';

type DialogProps = {
  open?: boolean;
  onClose?: () => void;
  title?: string;
};

type Props = {
  subscriptionId: string;
  onResumed?: (subscription: Subscription | TSubscriptionExpanded) => void;
  dialogProps?: DialogProps;
  successToast?: boolean;
  authToken?: string;
};

type RecoverInfo = {
  subscription: Subscription;
  needStake?: boolean;
};

const fetchSubscriptionDetail = async (params: {
  subscriptionId: string;
  authToken?: string;
}): Promise<TSubscriptionExpanded> => {
  const url = `/api/subscriptions/${params.subscriptionId}`;
  const res = await api.get(params.authToken ? joinURL(url, `?authToken=${params.authToken}`) : url);
  return res.data;
};

const fetchRecoverInfo = async (params: { subscriptionId: string; authToken?: string }): Promise<RecoverInfo> => {
  const url = `/api/subscriptions/${params.subscriptionId}/recover-info`;
  const res = await api.get(params.authToken ? joinURL(url, `?authToken=${params.authToken}`) : url);
  return res.data;
};

const recoverSubscription = async (params: {
  subscriptionId: string;
  authToken?: string;
}): Promise<{
  subscription: Subscription;
  needStake?: boolean;
}> => {
  const url = `/api/subscriptions/${params.subscriptionId}/recover`;
  const res = await api.put(params.authToken ? joinURL(url, `?authToken=${params.authToken}`) : url);
  return res.data;
};

function RecoverSubscription({
  subscriptionId,
  dialogProps = {
    open: true,
  },
  onResumed = () => {},
  successToast = true,
  authToken = undefined,
}: Props) {
  const { t, locale } = useLocaleContext();
  const { connect } = usePaymentContext();
  const [recoverLoading, setRecoverLoading] = useState(false);
  const [dialogOpen, setDialogOpen] = useState(dialogProps.open || false);

  const { data, error, loading } = useRequest(() => fetchRecoverInfo({ subscriptionId, authToken }), {
    ready: !!subscriptionId,
  });

  const isCrossOriginRequest = isCrossOrigin();
  const needStake = data?.needStake ?? false;

  const handleSuccess = async () => {
    try {
      // 获取最新的订阅数据
      const subscription = await fetchSubscriptionDetail({ subscriptionId, authToken });

      if (successToast) {
        Toast.success(t('payment.customer.recover.success'));
      }

      setDialogOpen(false);
      onResumed(subscription);
      setRecoverLoading(false);
    } catch (err) {
      console.error('Failed to fetch updated subscription:', err);
      Toast.error(formatError(err));
      setRecoverLoading(false);
    }
  };

  const handleRecoverWithStake = () => {
    setRecoverLoading(true);

    try {
      connect.open({
        locale: locale as 'en' | 'zh',
        containerEl: undefined as unknown as Element,
        saveConnect: false,
        action: 're-stake',
        prefix: joinURL(getPrefix(), '/api/did'),
        useSocket: !isCrossOriginRequest,
        extraParams: { subscriptionId },
        messages: {
          scan: t('common.connect.defaultScan'),
          title: t('payment.customer.recover.reStakeTitle'),
          confirm: t('common.connect.confirm'),
        } as any,
        onSuccess: handleSuccess,
        onClose: () => {
          connect.close();
          setRecoverLoading(false);
        },
        onError: (err: any) => {
          Toast.error(formatError(err));
          setRecoverLoading(false);
        },
      });
    } catch (err) {
      Toast.error(formatError(err));
      setRecoverLoading(false);
    }
  };

  const handleDirectRecover = async () => {
    setRecoverLoading(true);

    try {
      const result = await recoverSubscription({ subscriptionId, authToken });

      if (result.needStake) {
        handleRecoverWithStake();
        return;
      }
      const { subscription } = result;
      if (successToast) {
        Toast.success(t('payment.customer.recover.success'));
      }

      setDialogOpen(false);
      onResumed(subscription);
      setRecoverLoading(false);
    } catch (err: any) {
      Toast.error(formatError(err));
      setRecoverLoading(false);
    }
  };

  const handleRecover = () => {
    if (needStake) {
      handleRecoverWithStake();
    } else {
      handleDirectRecover();
    }
  };

  const handleClose = () => {
    setDialogOpen(false);
    dialogProps.onClose?.();
  };

  if (loading) {
    return null;
  }

  return (
    <Dialog
      PaperProps={{
        style: { minHeight: 'auto' },
      }}
      {...(dialogProps || {})}
      open={dialogOpen}
      title={dialogProps?.title || t('payment.customer.recover.title')}
      sx={{ '& .MuiDialogContent-root': { pt: 0 } }}
      onClose={handleClose}>
      {error ? (
        <Alert severity="error">{error.message}</Alert>
      ) : (
        <Stack
          sx={{
            gap: 2,
          }}>
          <Typography
            variant="body2"
            sx={{
              color: 'text.secondary',
            }}>
            {t('payment.customer.recover.description', {
              date: formatToDate(Number(data?.subscription?.current_period_end || '0') * 1000),
            })}
          </Typography>

          {needStake && <Alert severity="warning">{t('payment.customer.recover.stakeRequiredDescription')}</Alert>}

          <Stack
            direction="row"
            sx={{
              justifyContent: 'flex-end',
              gap: 2,
              mt: 2,
            }}>
            <Button variant="outlined" color="primary" onClick={handleClose}>
              {t('common.cancel')}
            </Button>
            <LoadingButton variant="contained" size="small" loading={recoverLoading} onClick={handleRecover}>
              {t('common.confirm')}
            </LoadingButton>
          </Stack>
        </Stack>
      )}
    </Dialog>
  );
}

export default RecoverSubscription;
