import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import {
  CustomerInvoiceList,
  formatBNStr,
  formatError,
  getPrefix,
  usePaymentContext,
  OverdueInvoicePayment,
} from '@blocklet/payment-react';

import type { GroupedBN, TCustomerExpanded } from '@blocklet/payment-types';
import {
  ExpandMore,
  AccountBalanceWalletOutlined,
  AddOutlined,
  CreditCardOutlined,
  AccountBalanceOutlined,
  InfoOutlined,
  AssignmentReturnOutlined,
} from '@mui/icons-material';
import {
  Avatar,
  Box,
  Button,
  FormControl,
  MenuItem,
  Select,
  Skeleton,
  Stack,
  Tooltip,
  Typography,
  Alert,
  Divider,
} from '@mui/material';
import type { SelectChangeEvent } from '@mui/material/Select';
import { styled } from '@mui/system';
import { useRequest, useSetState } from 'ahooks';
import { flatten, isEmpty } from 'lodash';
import { memo, useEffect, useState, Fragment } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { joinURL } from 'ufo';
import CreditOverview from '../../components/customer/credit-overview';
import ConditionalSection from '../../components/conditional-section';

import { useTransitionContext } from '../../components/progress-bar';
import CurrentSubscriptions from '../../components/subscription/portal/list';
import NotificationPreference from '../../components/customer/notification-preference';
import { useSessionContext } from '../../contexts/session';
import api from '../../libs/api';
import CustomerRevenueList from '../../components/payouts/portal/list';

type Result = TCustomerExpanded & {
  summary: { [key: string]: GroupedBN };
  creditSummary?: {
    grants?: { [key: string]: { totalAmount: string; remainingAmount: string; grantCount: number } };
    transactions?: any;
    pendingAmount?: { [key: string]: string };
  };
  error?: string;
};

const fetchData = (): Promise<Result> => {
  return api.get('/api/customers/me?skipError=true&create=true').then((res: any) => res.data);
};

const emptyObject = {};

const CurrencyCard = memo(
  ({
    label,
    data,
    currency,
    icon,
  }: {
    label: string;
    data: {
      [key: string]: string;
    };
    icon: any;
    currency: {
      id: string;
      decimal: number;
      payment_method_id: string;
      symbol: string;
    };
  }) => {
    const safeData = data || {};
    const value = formatBNStr(safeData[currency?.id], currency?.decimal, 6, true);

    return (
      <Box
        sx={{
          transition: 'all 0.2s ease-in-out',
          position: 'relative',
          height: '100%',
          display: 'flex',
          flexDirection: 'row',
          justifyContent: 'space-between',
          containerType: 'inline-size',
        }}>
        <Typography
          variant="body1"
          gutterBottom
          sx={{ color: 'text.secondary', display: 'flex', alignItems: 'center', gap: 1 }}>
          {icon}
          {label}
        </Typography>
        <Typography variant="body1" gutterBottom sx={{ color: 'text.primary', whiteSpace: 'nowrap' }}>
          {value} {currency.symbol}
        </Typography>
      </Box>
    );
  }
);

const CardSkeleton = memo(({ height = 100 }: { height: number }) => {
  return (
    <Box className="base-card section">
      <Box
        className="section-header"
        sx={{
          display: 'flex',
          justifyContent: 'space-between',
          alignItems: 'center',
          mb: 2,
        }}>
        <Skeleton variant="text" width={150} height={32} />
      </Box>
      <Skeleton variant="rectangular" height={height} />
    </Box>
  );
});

function SummaryCardSkeleton() {
  return (
    <Box className="base-card section section-summary">
      <Skeleton variant="text" width={150} height={32} sx={{ mb: 2 }} />
      <Skeleton variant="rectangular" height={88} width="100%" />
    </Box>
  );
}

function isSummaryEmpty(summary: any, id: string) {
  const summaryKeys = ['balance', 'paid', 'stake', 'refund', 'due'];
  return summaryKeys.every((key) => !summary?.[key]?.[id] || summary?.[key]?.[id] === '0');
}

// 定义卡片类型
type CardType = 'balance' | 'spent' | 'stake' | 'refund' | 'due';

// 定义一个统一的卡片配置
const CARD_CONFIG: Record<CardType, { key: keyof typeof summaryKeyMap; alwaysShow?: boolean }> = {
  balance: { key: 'token' },
  spent: { key: 'paid', alwaysShow: true },
  stake: { key: 'stake' },
  refund: { key: 'refund' },
  due: { key: 'due' },
} as const;

// 映射 summary 中的键名
const summaryKeyMap = {
  token: 'token',
  paid: 'paid',
  stake: 'stake',
  refund: 'refund',
  due: 'due',
} as const;

const isCardVisible = (type: string, config: any, data: any, currency: any, method: any) => {
  const summaryKey = config.key;
  const hasSummaryValue =
    data?.summary?.[summaryKey]?.[currency.id] && data?.summary?.[summaryKey]?.[currency.id] !== '0';

  if (type === 'balance') {
    return method?.type === 'arcblock' || config.alwaysShow || hasSummaryValue;
  }

  return config.alwaysShow || hasSummaryValue;
};

const getCardIcon = (type: CardType) => {
  const iconMap = {
    balance: <AccountBalanceWalletOutlined color="success" fontSize="small" />,
    spent: <CreditCardOutlined color="warning" fontSize="small" />,
    stake: <AccountBalanceOutlined fontSize="small" color="info" />,
    refund: <AssignmentReturnOutlined fontSize="small" sx={{ color: 'chip.secondary.text' }} />,
    due: <InfoOutlined fontSize="small" color="error" />,
  };
  return iconMap[type];
};

export default function CustomerHome() {
  const { t } = useLocaleContext();
  const { events } = useSessionContext();
  const { settings } = usePaymentContext();
  const [domFilter, setDomFilter] = useSetState<any>({
    credit: '',
    revenue: '',
  });
  const [subscriptionLoading, setSubscriptionLoading] = useState(false);
  const currencies = flatten(
    settings.paymentMethods?.map((method) =>
      (method.payment_currencies || []).map((c) => ({
        ...c,
        methodName: method.name,
      }))
    )
  );
  const [params] = useSearchParams();
  const embed = params.get('embed') || sessionStorage.getItem('embed');

  const { livemode, setLivemode } = usePaymentContext();
  const [state, setState] = useSetState({
    editing: false,
    loading: false,
    onlyActive: true,
    setOverdraftProtection: false,
  });
  const navigate = useNavigate();
  const [subscriptionStatus, setSubscriptionStatus] = useState(false);
  const [hasSubscriptions, setHasSubscriptions] = useState(false);
  const { startTransition } = useTransitionContext();
  const {
    data,
    error,
    runAsync,
    loading = true,
  } = useRequest(fetchData, {
    manual: true,
    onSuccess: async (res) => {
      if (!hasSubscriptions) {
        const search = new URLSearchParams();
        const searchParams = {
          page: 1,
          pageSize: 5,
          showTotalCount: true,
          customer_id: res.id,
        };
        Object.entries(searchParams).forEach(([key, value]) => {
          search.set(key, String(value));
        });
        const { data: subscriptions } = await api.get(`/api/subscriptions?${search.toString()}`);
        if (subscriptions.totalCount > 0 || subscriptions.count > 0) {
          setHasSubscriptions(true);
        }
      }
    },
  });

  const loadingCard = loading || !data;
  const [showOverduePayment, setShowOverduePayment] = useState(false);

  useEffect(() => {
    runAsync();
    events.on('switch-did', () => {
      runAsync();
    });
  }, []);

  useEffect(() => {
    if (data && !data.error && data.livemode !== livemode) {
      setLivemode(data.livemode);
    }
  }, [data]);

  if (error) {
    return (
      <Box
        sx={{
          backgroundColor: 'error.light',
          color: 'error.dark',
          p: 1,
          mb: 2,
          borderRadius: 1,
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}>
        <Typography variant="body2">{formatError(error)}</Typography>
      </Box>
    );
  }

  const handleRecharge = (currency: any) => {
    if (currency?.id) {
      navigate(`/customer/recharge/${currency.id}`);
    }
  };

  // const handleAddCredit = (currency: any) => {
  //   if (currency?.id) {
  //     navigate(`/customer/credit-packages?currency=${currency.id}`);
  //   }
  // };

  const onToggleActive = (e: SelectChangeEvent) => {
    setSubscriptionLoading(true);
    setState({ onlyActive: e.target.value === 'active' });
    setTimeout(() => {
      setSubscriptionLoading(false);
    }, 300);
  };

  // const handleViewCreditDetails = (currencyId: string) => {
  //   navigate(`/customer/credit-grants?currency=${currencyId}`);
  // };

  const SubscriptionCard =
    loadingCard || !hasSubscriptions ? null : (
      <Box className="base-card section section-subscription">
        <Box className="section-header">
          <Typography variant="h3">{t('customer.subscription.title')}</Typography>
          <Stack
            direction="row"
            spacing={1}
            sx={{
              alignItems: 'center',
            }}>
            <NotificationPreference />
            {subscriptionStatus && (
              <FormControl
                sx={{
                  '.MuiInputBase-root': {
                    background: 'none',
                    border: 'none',
                  },
                  '.MuiOutlinedInput-notchedOutline': {
                    border: 'none',
                  },
                }}>
                <Select
                  value={state.onlyActive ? 'active' : ''}
                  onChange={onToggleActive}
                  displayEmpty
                  IconComponent={ExpandMore}
                  inputProps={{ 'aria-label': 'Without label' }}>
                  <MenuItem value="">All</MenuItem>
                  <MenuItem value="active">Active</MenuItem>
                </Select>
              </FormControl>
            )}
          </Stack>
        </Box>
        <Box className="section-body">
          {subscriptionLoading ? (
            <Box>{t('common.loading')}</Box>
          ) : (
            <CurrentSubscriptions
              id={data?.id}
              onlyActive={state.onlyActive}
              changeActive={(v) => setState({ onlyActive: v })}
              status={state.onlyActive ? 'active,trialing,past_due' : 'active,trialing,paused,past_due,canceled'}
              style={{
                cursor: 'pointer',
              }}
              onClickSubscription={(subscription) => {
                startTransition(() => {
                  navigate(`/customer/subscription/${subscription.id}`);
                });
              }}
              setStatusState={setSubscriptionStatus}
              setHasSubscriptions={setHasSubscriptions}
            />
          )}
        </Box>
      </Box>
    );

  const SummaryCard = loadingCard ? (
    <SummaryCardSkeleton />
  ) : (
    <Box className="base-card section section-summary" sx={{ containerType: 'inline-size' }}>
      {data?.summary && (
        <>
          <Box className="section-header">
            <Typography variant="h3">{t('admin.customer.summary.stats')}</Typography>
          </Box>
          <Stack
            sx={{
              gap: 2,
              mt: 2,
              display: 'grid',

              gridTemplateColumns: {
                xs: 'repeat(1, 1fr)',
                md: 'repeat(2, 1fr)',
              },

              '@container (max-width: 600px)': {
                gridTemplateColumns: 'repeat(1, 1fr)',
              },
            }}>
            {currencies.map((c) => {
              const method = settings?.paymentMethods?.find((m) => m.id === c.payment_method_id);
              if (method?.type !== 'arcblock') {
                return null;
              }
              return isSummaryEmpty(data?.summary, c.id) && c.id !== settings.baseCurrency.id ? null : (
                <Stack
                  key={c.id}
                  sx={{
                    borderRadius: 1,
                    p: 2,
                    gap: 2,
                    border: '1px solid',
                    borderColor: 'divider',
                    boxShadow: 1,
                  }}>
                  <Stack
                    sx={{
                      flexDirection: 'row',
                      justifyContent: 'space-between',
                    }}>
                    <Box
                      sx={{
                        alignItems: 'center',
                        display: 'flex',
                        gap: 1,
                      }}>
                      <Avatar src={c?.logo} alt={c?.symbol} sx={{ width: 18, height: 18 }} />
                      <Typography
                        variant="h5"
                        component="div"
                        sx={{ fontSize: '16px', color: 'text.primary', fontWeight: '500' }}>
                        {c?.symbol}
                      </Typography>
                      <Typography
                        sx={{
                          color: 'text.lighter',
                          fontSize: 12,
                        }}>
                        {c?.methodName}
                      </Typography>
                    </Box>

                    {method?.type === 'arcblock' && (
                      <Tooltip title={t('customer.recharge.rechargeTooltip')} arrow placement="top">
                        <Button onClick={() => handleRecharge(c)} variant="text" color="primary" size="small">
                          <AddOutlined fontSize="small" />
                          <Typography variant="body2" className="recharge-title">
                            {t('customer.recharge.title')}
                          </Typography>
                        </Button>
                      </Tooltip>
                    )}
                  </Stack>
                  <Divider />

                  <Stack
                    className="section-body"
                    sx={{
                      gap: 1,
                      mt: 1.5,
                    }}>
                    {Object.entries(CARD_CONFIG).map(([type, config]) => {
                      if (!isCardVisible(type, config, data, c, method)) {
                        return null;
                      }

                      return (
                        <Box
                          key={`card-${c.id}-${type}`}
                          className="card-item"
                          sx={{
                            position: 'relative',
                          }}>
                          <CurrencyCard
                            label={t(`admin.customer.summary.${type}`)}
                            data={data?.summary?.[config.key] || emptyObject}
                            currency={c}
                            icon={getCardIcon(type as CardType)}
                          />
                        </Box>
                      );
                    })}
                  </Stack>
                </Stack>
              );
            })}
          </Stack>
        </>
      )}
    </Box>
  );

  // 独立的Credit Card组件
  const CreditCard = (
    <ConditionalSection skeleton={loadingCard} onStateChange={(val) => setDomFilter({ credit: val })}>
      <Box className="base-card section section-credit">
        <Box className="section-header" sx={{ mb: 2 }}>
          <Typography variant="h3">{t('admin.creditGrants.title')}</Typography>
        </Box>
        <CreditOverview customerId={data?.id || ''} settings={settings} />
      </Box>
    </ConditionalSection>
  );

  const InvoiceCard = loadingCard ? (
    <CardSkeleton height={200} />
  ) : (
    <Box className="base-card section section-invoices">
      <Box className="section-header">
        <Typography variant="h3">{t('customer.invoiceHistory')}</Typography>
        {isEmpty(data?.summary?.due) === false && (
          <Tooltip title={t('payment.customer.pastDue.warning')}>
            <Button
              variant="text"
              color="error"
              component="a"
              size="small"
              href={joinURL(getPrefix(), '/customer/invoice/past-due', `${embed === '1' ? '?embed=1' : ''}`)}
              target="_blank"
              rel="noreferrer"
              style={{ textDecoration: 'none', fontSize: 13 }}>
              {t('payment.customer.pastDue.invoices')}
            </Button>
          </Tooltip>
        )}
      </Box>
      <Box className="section-body">
        <CustomerInvoiceList customer_id={data?.id} type="table" include_staking relatedSubscription />
      </Box>
    </Box>
  );

  const RevenueCard = (
    <ConditionalSection skeleton={loadingCard} onStateChange={(val) => setDomFilter({ revenue: val })}>
      <Box className="base-card section section-revenue">
        <Box className="section-header">
          <Typography variant="h3">{t('customer.payout.title')}</Typography>
        </Box>
        <Box className="section-body">
          <CustomerRevenueList />
        </Box>
      </Box>
    </ConditionalSection>
  );

  const cards = [
    { card: SummaryCard, key: 'summary' },
    { card: CreditCard, key: 'credit' },
    { card: SubscriptionCard, key: 'subscription' },
    { card: InvoiceCard, key: 'invoice' },
    { card: RevenueCard, key: 'revenue' },
  ];

  const visibleCards = cards.filter(({ card, key }) => card && domFilter[key] !== 'none');

  return (
    <Content>
      {data?.error && (
        <Alert severity="error" sx={{ mb: 2 }}>
          {data?.error}
        </Alert>
      )}
      {isEmpty(data?.summary?.due) === false && (
        <Alert
          severity="error"
          sx={{
            mb: 2,
            '.MuiAlert-action': {
              alignItems: 'center',
            },
          }}
          action={
            <Button
              color="inherit"
              size="small"
              variant="outlined"
              onClick={() => setShowOverduePayment(true)}
              sx={{ whiteSpace: 'nowrap' }}>
              {t('customer.pastDue.payNow')}
            </Button>
          }>
          {t('customer.pastDue.alert')}
        </Alert>
      )}
      {showOverduePayment && data && (
        <OverdueInvoicePayment
          customerId={data.id}
          onPaid={() => {
            setShowOverduePayment(false);
            runAsync();
          }}
          successToast={false}
          detailLinkOptions={{
            enabled: true,
            onClick: () => {
              setShowOverduePayment(false);
              navigate('/customer/invoice/past-due');
            },
          }}
          dialogProps={{
            open: showOverduePayment,
            onClose: () => {
              setShowOverduePayment(false);
              runAsync();
            },
            title: t('customer.pastDue.title'),
          }}
        />
      )}
      <Root>
        {visibleCards.map(({ card, key }, index, array) => (
          <Fragment key={key}>
            {card}
            {(domFilter[key] ? domFilter[key] === 'visible' : index < array.length - 1) && <Divider />}
          </Fragment>
        ))}
      </Root>
    </Content>
  );
}

const Content = styled(Stack)`
  height: 100%;
  .section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  a {
    text-decoration: underline;
  }
  .section {
    height: fit-content;
  }
  .base-card {
    border: none;
    padding: 0;
    box-shadow: none;
  }
  @media (max-width: ${({ theme }) => theme.breakpoints.values.md}px) {
    padding: 0px;
    .base-card {
      border: none;
      box-shadow: none;
    }
  }
`;

const Root = styled(Stack)`
  gap: 24px;
  display: flex;
  flex-direction: column;
  .section-body {
    padding: 0 1px;
  }
  @media (max-width: ${({ theme }) => theme.breakpoints.values.xl}px) {
    padding: 0px;
    .base-card {
      border: none;
      box-shadow: none;
      padding-left: 0;
      padding-right: 0;
    }
    .section-summary {
      padding-top: 0;
    }
  }
`;
