import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import Toast from '@arcblock/ux/lib/Toast';
import {
  api,
  findCurrency,
  formatError,
  formatTime,
  useMobile,
  usePaymentContext,
  Status,
  ConfirmDialog,
  formatAmount,
} from '@blocklet/payment-react';
import { ArrowBackOutlined, AddOutlined } from '@mui/icons-material';
import { Alert, AlertTitle, Box, Button, CircularProgress, Divider, Stack, Typography } from '@mui/material';
import { styled } from '@mui/system';
import { useRequest, useSetState } from 'ahooks';
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import { dispatch } from 'use-bus';

import Copyable from '../../../../components/copyable';
import EventList from '../../../../components/event/list';
import InfoMetric from '../../../../components/info-metric';
import InfoRow from '../../../../components/info-row';
import InfoRowGroup from '../../../../components/info-row-group';
import MetadataEditor from '../../../../components/metadata/editor';
import MetadataList from '../../../../components/metadata/list';
import SectionHeader from '../../../../components/section/header';
import { goBackOrFallback } from '../../../../libs/util';
import PromotionCodesList from '../promotion-codes/list';
import PromotionCodeModal from '../promotion-codes/create';
import CouponRenameModal from './edit';
import ActiveRedemptions from '../../../../components/promotion/active-redemptions';
import ApplicableProductsList from './applicable-products';
import CurrencyRestrictions from '../../../../components/promotion/currency-restrictions';

const getCoupon = (id: string): Promise<any> => {
  return api.get(`/api/coupons/${id}`).then((res: any) => res.data);
};

export default function CouponDetail(props: { id: string }) {
  const { t } = useLocaleContext();
  const { isMobile } = useMobile();
  const navigate = useNavigate();
  const { settings, setLivemode } = usePaymentContext();
  const [promotionCodeModalOpen, setPromotionCodeModalOpen] = useState(false);
  const [renameModalOpen, setRenameModalOpen] = useState(false);
  const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);
  const [state, setState] = useSetState({
    editing: {
      metadata: false,
    },
    loading: {
      metadata: false,
      coupon: false,
      delete: false,
    },
  });

  const { loading, error, data, runAsync } = useRequest(() => getCoupon(props.id), {
    onSuccess: (res) => {
      setLivemode(!!res.livemode);
    },
  });

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

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

  const createCouponUpdater = (key: string) => async (updates: any) => {
    try {
      setState((prev) => ({ loading: { ...prev.loading, [key]: true } }));
      await api.put(`/api/coupons/${props.id}`, updates);
      Toast.success(t('common.saved'));
      dispatch('coupon.updated');
      runAsync();
    } catch (err) {
      console.error(err);
      Toast.error(formatError(err));
    } finally {
      setState((prev) => ({ loading: { ...prev.loading, [key]: false } }));
    }
  };

  const onUpdateMetadata = async (updates: any) => {
    try {
      setState((prev) => ({ loading: { ...prev.loading, metadata: true } }));
      await api.put(`/api/coupons/${props.id}`, { metadata: updates.metadata });
      Toast.success(t('common.saved'));
      dispatch('coupon.updated');
      runAsync();
    } catch (err) {
      console.error(err);
      Toast.error(formatError(err));
    } finally {
      setState((prev) => ({ loading: { ...prev.loading, metadata: false } }));
    }
  };

  const handleUpdateCoupon = async (updates: { name: string; description?: string }) => {
    await createCouponUpdater('coupon')(updates);
  };

  const handleDeleteCoupon = async () => {
    try {
      setState((prev) => ({ loading: { ...prev.loading, delete: true } }));
      await api.delete(`/api/coupons/${props.id}`);
      Toast.success(t('admin.coupon.deletedSuccessfully'));
      dispatch('coupon.deleted');
      navigate('/admin/products/coupons');
    } catch (err) {
      console.error(err);
      Toast.error(formatError(err));
    } finally {
      setState((prev) => ({ loading: { ...prev.loading, delete: false } }));
      setDeleteConfirmOpen(false);
    }
  };

  const handleDeleteClick = () => {
    setDeleteConfirmOpen(true);
  };

  const canDelete = !data?.locked && (!data?.promotion_codes || data.promotion_codes.length === 0);

  const handleEditMetadata = () => {
    setState((prev) => ({ editing: { ...prev.editing, metadata: true } }));
  };

  const formatCouponTerms = (coupon: any) => {
    let couponOff = '';
    if (coupon.percent_off && coupon.percent_off > 0) {
      couponOff = `${coupon.percent_off}%`;
    }
    if (coupon.amount_off && coupon.amount_off !== '0') {
      const currency = findCurrency(settings.paymentMethods, coupon.currency_id) || settings.baseCurrency;
      couponOff = `${formatAmount(coupon.amount_off, currency.decimal)} ${currency.symbol}`;
    }
    if (couponOff) {
      return t(`admin.coupon.couponTerms.${coupon.duration}`, { couponOff, months: coupon.duration_in_months });
    }
    return t('admin.coupon.noDiscount');
  };

  const formatCouponDiscount = () => {
    if (data.percent_off && data.percent_off > 0) {
      return t('admin.coupon.couponTermsPercentage', { percent: data.percent_off });
    }
    if (data.amount_off && data.amount_off !== '0') {
      const currency = findCurrency(settings.paymentMethods, data.currency_id) || settings.baseCurrency;
      return t('admin.coupon.couponTermsFixedAmount', {
        amount: formatAmount(data.amount_off, currency.decimal),
        symbol: currency.symbol,
      });
    }
    return t('admin.coupon.noDiscount');
  };

  const formatDuration = () => {
    if (data.duration === 'repeating' && data.duration_in_months) {
      return t(`admin.coupon.couponTermsDuration.${data.duration}`, { months: data.duration_in_months });
    }
    return t(`admin.coupon.couponTermsDuration.${data.duration}`);
  };

  const formatRedemptions = () => {
    const maxRedemptions = data.max_redemptions ? data.max_redemptions.toString() : t('admin.coupon.unlimited');
    const timesRedeemed = data.times_redeemed || 0;
    return `${timesRedeemed} / ${maxRedemptions}`;
  };

  // Get available currencies based on coupon configuration
  const getAvailableCurrencies = () => {
    const allCurrencies = settings.paymentMethods?.flatMap((pm) => pm.payment_currencies) || [];

    if (data.percent_off) {
      // Percentage coupon: return all available currencies
      return allCurrencies;
    }
    // Fixed amount coupon: return coupon's configured currencies
    const currencyIds = new Set<string>();

    // Add base currency
    if (data.currency_id) {
      currencyIds.add(data.currency_id);
    }

    // Add additional configured currencies
    if (data.currency_options && typeof data.currency_options === 'object') {
      Object.keys(data.currency_options).forEach((currencyId) => {
        currencyIds.add(currencyId);
      });
    }

    return allCurrencies.filter((currency) => currencyIds.has(currency.id));
  };

  const availableCurrencies = getAvailableCurrencies();

  return (
    <Root direction="column" spacing={2.5} sx={{ mb: 4 }}>
      <Box>
        {!data.valid && (
          <Alert severity="warning">
            <AlertTitle>{t('admin.coupon.inactive')}</AlertTitle>
            {t('admin.coupon.inactiveTip')}
          </Alert>
        )}
        <Stack
          className="page-header"
          direction="row"
          sx={{
            justifyContent: 'space-between',
            alignItems: 'center',
          }}>
          <Stack
            direction="row"
            onClick={() => goBackOrFallback('/admin/products/coupons')}
            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('admin.coupons')}
            </Typography>
          </Stack>
          <Stack direction="row" spacing={2}>
            <Button variant="contained" color="primary" onClick={() => setRenameModalOpen(true)}>
              {t('common.edit')}
            </Button>
            {canDelete && (
              <Button
                variant="outlined"
                color="error"
                onClick={handleDeleteClick}
                disabled={state.loading.delete}
                title={
                  !canDelete && data?.promotion_codes?.length > 0
                    ? t('admin.coupon.cannotDeleteWithPromotionCodes')
                    : undefined
                }>
                {state.loading.delete ? t('common.deleting') : t('common.delete')}
              </Button>
            )}
          </Stack>
        </Stack>
        <Box
          sx={{
            mt: 4,
            mb: 3,
            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="column"
              sx={{
                alignItems: 'flex-start',
                justifyContent: 'space-around',
              }}>
              <Typography
                variant="h2"
                sx={{
                  color: 'text.primary',
                }}>
                {data.name}
              </Typography>
              <Typography
                variant="subtitle1"
                sx={{
                  color: 'text.lighter',
                }}>
                {formatCouponTerms(data)}
              </Typography>
            </Stack>
          </Stack>
          <Stack
            className="section-body"
            sx={{
              justifyContent: 'flex-start',
              flexWrap: 'wrap',
              'hr.MuiDivider-root:last-child': {
                display: 'none',
              },
              flexDirection: {
                xs: 'column',
                sm: 'column',
                md: 'row',
              },
              alignItems: 'flex-start',
              gap: {
                xs: 1,
                sm: 1,
                md: 3,
              },
            }}>
            <InfoMetric
              label={t('admin.coupon.id')}
              value={<Copyable text={props.id} style={{ marginLeft: 4 }} />}
              divider
            />
            <InfoMetric label={t('admin.coupon.redemptions')} value={formatRedemptions()} divider />
            <InfoMetric
              label={t('common.status')}
              value={
                <Status
                  label={data.valid ? t('common.active') : t('common.inactive')}
                  color={data.valid ? 'success' : 'default'}
                />
              }
              divider
            />
            <InfoMetric label={t('common.created')} value={formatTime(data.created_at)} divider />
          </Stack>
        </Box>
        <Divider />
      </Box>
      <Stack
        sx={{
          flexDirection: {
            xs: 'column',
            lg: 'row',
          },
          gap: {
            xs: 2.5,
            md: 4,
          },
          '.coupon-column-1': {
            minWidth: {
              xs: '100%',
              lg: '600px',
            },
          },
          '.coupon-column-2': {
            width: {
              xs: '100%',
              md: '100%',
              lg: '320px',
            },
            maxWidth: {
              xs: '100%',
              md: '33%',
            },
          },
        }}>
        <Box
          className="coupon-column-1"
          sx={{
            flex: 1,
            gap: 2.5,
            display: 'flex',
            flexDirection: 'column',
          }}>
          <Box className="section" sx={{ containerType: 'inline-size' }}>
            <SectionHeader title={t('common.details')} />
            <InfoRowGroup
              sx={{
                display: 'grid',
                gridTemplateColumns: {
                  xs: 'repeat(1, 1fr)',
                  xl: 'repeat(2, 1fr)',
                },
                '@container (min-width: 1000px)': {
                  gridTemplateColumns: 'repeat(2, 1fr)',
                },
                '.info-row-wrapper': {
                  gap: 1,
                  flexDirection: {
                    xs: 'column',
                    xl: 'row',
                  },
                  alignItems: {
                    xs: 'flex-start',
                    xl: 'center',
                  },
                  '@container (min-width: 1000px)': {
                    flexDirection: 'row',
                    alignItems: 'center',
                  },
                },
              }}>
              <InfoRow label={t('admin.coupon.name')} value={data.name} />
              {data.description && <InfoRow label={t('admin.coupon.desc')} value={data.description} />}
              <InfoRow label={t('admin.coupon.discount')} value={formatCouponDiscount()} />
              <InfoRow label={t('admin.coupon.duration')} value={formatDuration()} />
              <InfoRow
                label={t('admin.coupon.maxRedemptions')}
                value={data.max_redemptions || t('admin.coupon.unlimited')}
              />
              <InfoRow label={t('admin.coupon.timesRedeemed')} value={data.times_redeemed || 0} />
              <InfoRow
                label={t('admin.coupon.expires')}
                value={data.redeem_by ? formatTime(data.redeem_by * 1000) : t('common.never')}
              />
              <InfoRow label={t('admin.coupon.updated')} value={formatTime(data.updated_at)} />
            </InfoRowGroup>
          </Box>
          <Divider />
          {data.currency_options && Object.keys(data.currency_options).length > 0 && (
            <>
              <Box className="section">
                <SectionHeader title={t('admin.coupon.currencies')} />
                <Box className="section-body">
                  <CurrencyRestrictions currencyOptions={data.currency_options} type="coupon" />
                </Box>
              </Box>
              <Divider />
            </>
          )}
          {data.applied_products && data.applied_products.length > 0 && (
            <>
              <Box className="section">
                <SectionHeader title={t('admin.coupon.applicableProducts')} />
                <Box className="section-body">
                  <ApplicableProductsList products={data.applied_products} />
                </Box>
              </Box>
              <Divider />
            </>
          )}
          <Box className="section">
            <SectionHeader title={t('admin.coupon.promotionCodes')}>
              <Button
                variant="text"
                color="inherit"
                size="small"
                startIcon={<AddOutlined />}
                sx={{ color: 'text.link' }}
                onClick={() => setPromotionCodeModalOpen(true)}>
                {t('admin.coupon.addPromotionCode')}
              </Button>
            </SectionHeader>
            <Box className="section-body">
              <PromotionCodesList couponId={props.id} />
            </Box>
          </Box>
          <Divider />
          <Box className="section">
            <SectionHeader title={t('admin.coupon.activeRedemptions')} />
            <Box className="section-body">
              <ActiveRedemptions couponId={props.id} />
            </Box>
          </Box>
          <Divider />
          <Box className="section">
            <SectionHeader title={t('common.events')} />
            <Box className="section-body">
              <EventList features={{ toolbar: false }} object_id={data.id} />
            </Box>
          </Box>
        </Box>
        {isMobile && <Divider />}
        <Box className="coupon-column-2" sx={{ gap: 2.5, display: 'flex', flexDirection: 'column' }}>
          <Box className="section">
            <SectionHeader title={t('common.metadata.label')}>
              <Button
                variant="text"
                color="inherit"
                size="small"
                sx={{ color: 'text.link' }}
                disabled={state.editing.metadata}
                onClick={handleEditMetadata}>
                {t('common.edit')}
              </Button>
            </SectionHeader>
            <Box className="section-body">
              <MetadataList data={data.metadata} handleEditMetadata={handleEditMetadata} />
              {state.editing.metadata && (
                <MetadataEditor
                  data={data}
                  loading={state.loading.metadata}
                  onSave={onUpdateMetadata}
                  onCancel={() => setState((prev) => ({ editing: { ...prev.editing, metadata: false } }))}
                />
              )}
            </Box>
          </Box>
        </Box>
      </Stack>

      <PromotionCodeModal
        open={promotionCodeModalOpen}
        onClose={() => setPromotionCodeModalOpen(false)}
        onSubmit={() => setPromotionCodeModalOpen(false)}
        couponId={props.id}
        availableCurrencies={availableCurrencies}
      />

      <CouponRenameModal
        open={renameModalOpen}
        onClose={() => setRenameModalOpen(false)}
        onSave={handleUpdateCoupon}
        initialName={data.name}
        initialDescription={data.description || ''}
        loading={state.loading.coupon}
      />

      {deleteConfirmOpen && (
        <ConfirmDialog
          onConfirm={handleDeleteCoupon}
          onCancel={() => setDeleteConfirmOpen(false)}
          title={t('admin.coupon.deleteConfirmTitle')}
          message={t('admin.coupon.deleteConfirmMessage')}
          loading={state.loading.delete}
        />
      )}
    </Root>
  );
}

const Root = styled(Stack)``;
