/* eslint-disable no-nested-ternary */
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import Toast from '@arcblock/ux/lib/Toast';
import type { PriceCurrency, PriceRecurring, TPricingTableExpanded, TPricingTableItem } from '@blocklet/payment-types';
import { CheckOutlined } from '@mui/icons-material';
import {
  Avatar,
  Box,
  Chip,
  List,
  ListItem,
  ListItemIcon,
  ListItemText,
  MenuItem,
  Select,
  Stack,
  ToggleButton,
  ToggleButtonGroup,
  Typography,
} from '@mui/material';
import { styled } from '@mui/system';
import { useSetState } from 'ahooks';
import { useEffect, useMemo, useState } from 'react';

import { BN } from '@ocap/util';
import isEmpty from 'lodash/isEmpty';
import { usePaymentContext } from '../contexts/payment';
import {
  formatError,
  formatPriceAmount,
  formatRecurring,
  getPriceCurrencyOptions,
  getPriceUintAmountByCurrency,
  isMobileSafari,
} from '../libs/util';
import { useMobile } from '../hooks/mobile';
import TruncatedText from './truncated-text';
import LoadingButton from './loading-button';

type SortOrder = { [key: string]: number };

const sortOrder: SortOrder = {
  year: 1,
  month: 2,
  day: 3,
  hour: 4,
};

const groupItemsByRecurring = (items: TPricingTableItem[], currency: { id: string; symbol: string }) => {
  const grouped: { [key: string]: TPricingTableItem[] } = {};
  const recurring: { [key: string]: PriceRecurring } = {};

  (items || []).forEach((x) => {
    const key = [x.price.recurring?.interval, x.price.recurring?.interval_count].join('-');
    if (x.price.currency_options?.find((c: PriceCurrency) => c.currency_id === currency.id)) {
      recurring[key] = x.price.recurring as PriceRecurring;
    }
    if (!grouped[key]) {
      grouped[key] = [];
    }

    // @ts-ignore
    grouped[key].push(x);
  });

  return { recurring, grouped };
};

type Props = {
  table: TPricingTableExpanded;
  onSelect: (priceId: string, currencyId: string) => void;
  alignItems?: 'center' | 'left';
  mode?: 'checkout' | 'select';
  interval?: string;
  hideCurrency?: boolean;
};

export default function PricingTable({
  table,
  alignItems = 'center',
  interval = '',
  mode = 'checkout',
  onSelect,
  hideCurrency = false,
}: Props) {
  const { t, locale } = useLocaleContext();
  const { isMobile } = useMobile();
  const {
    settings: { paymentMethods = [] },
    livemode,
    setLivemode,
    refresh,
  } = usePaymentContext();
  const isMobileSafariEnv = isMobileSafari();

  useEffect(() => {
    if (table) {
      if (livemode !== table.livemode) {
        setLivemode(table.livemode);
      }
    }
  }, [table, livemode, setLivemode, refresh]);

  const [currency, setCurrency] = useState(table.currency || {});
  const { recurring, grouped } = useMemo(() => groupItemsByRecurring(table.items, currency), [table.items, currency]);
  const recurringKeysList = useMemo(() => {
    if (isEmpty(recurring)) {
      return [];
    }
    return Object.keys(recurring).sort((a, b) => {
      const [aType, aValue] = a.split('-');
      const [bType, bValue] = b.split('-');
      if (sortOrder[aType] !== sortOrder[bType]) {
        return sortOrder[aType] - sortOrder[bType];
      }
      if (aValue && bValue) {
        // @ts-ignore
        return bValue - aValue;
      }
      // @ts-ignore
      return b - a;
    });
  }, [recurring]);
  const [state, setState] = useSetState({ interval });
  const currencyMap = useMemo(() => {
    if (!paymentMethods || paymentMethods.length === 0) {
      return {};
    }
    const ans: { [key: string]: any } = {};
    paymentMethods.forEach((paymentMethod) => {
      const { payment_currencies: paymentCurrencies = [] } = paymentMethod;
      if (paymentCurrencies && paymentCurrencies.length > 0) {
        paymentCurrencies.forEach((x: { id: string; symbol: string }) => {
          ans[x.id] = {
            ...x,
            method: paymentMethod.name,
          };
        });
      }
    });
    return ans;
  }, [paymentMethods]);

  const currencyList = useMemo(() => {
    const visited: { [key: string]: boolean } = {};
    if (!state.interval) {
      return [];
    }
    (grouped[state.interval] || []).forEach((x: TPricingTableItem) => {
      getPriceCurrencyOptions(x.price).forEach((c: PriceCurrency) => {
        visited[c?.currency_id] = true;
      });
    });
    return Object.keys(visited)
      .map((x) => currencyMap[x])
      .filter((v) => v);
  }, [currencyMap, grouped, state.interval]);
  const productList = useMemo(() => {
    return (grouped[state.interval as string] || []).filter((x: TPricingTableItem) => {
      const price = getPriceUintAmountByCurrency(x.price, currency);
      if (new BN(price).isZero() || !price) {
        return false;
      }
      return true;
    });
  }, [grouped, state.interval, currency]);

  useEffect(() => {
    if (table) {
      if (!state.interval || !grouped[state.interval]) {
        const keys = Object.keys(recurring);
        if (keys[0]) {
          setState({ interval: keys[0] });
        }
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [table]);

  const Root = styled(Box)`
    .btn-row {
      display: flex;
      flex-wrap: wrap;
      justify-content: space-between;
      align-items: center;
      width: 100%;
      gap: 20px;
    }
    .price-table-wrap {
      scrollbar-width: none;
      -ms-overflow-style: none;
      &::-webkit-scrollbar {
        display: none;
      }
    }
    @media (max-width: ${({ theme }) => theme.breakpoints.values.sm}px) {
      // .price-table-item {
      //   width: 90% !important;
      // }
      // .btn-row {
      //   padding: 0 20px;
      // }
    }
    @media (min-width: ${({ theme }) => theme.breakpoints.values.md}px) {
      .price-table-wrap:has(> div:nth-of-type(1)) {
        max-width: 360px !important;
      }
      .price-table-wrap:has(> div:nth-of-type(2)) {
        max-width: 780px !important;
      }
      .price-table-wrap:has(> div:nth-of-type(3)) {
        max-width: 1200px !important;
      }
    }
  `;
  return (
    <Root
      sx={{
        flex: 1,
        overflow: {
          xs: isMobileSafariEnv ? 'visible' : 'hidden',
          md: 'hidden',
        },
        display: 'flex',
        flexDirection: 'column',
      }}>
      <Stack
        direction="column"
        alignItems={alignItems === 'center' ? 'center' : 'flex-start'}
        sx={{
          gap: {
            xs: 3,
            sm: mode === 'select' ? 3 : 5,
          },
          height: '100%',
          overflow: {
            xs: 'auto',
            md: 'hidden',
          },
        }}>
        <Stack className="btn-row" flexDirection="row">
          {recurringKeysList.length > 0 && (
            <Box>
              {isMobile && recurringKeysList.length > 1 ? (
                <Select
                  value={state.interval}
                  onChange={(e) => setState({ interval: e.target.value })}
                  size="small"
                  sx={{ m: 1 }}>
                  {recurringKeysList.map((x) => (
                    <MenuItem key={x} value={x}>
                      <Typography color={x === state.interval ? 'text.primary' : 'text.secondary'}>
                        {formatRecurring(recurring[x] as PriceRecurring, true, '', locale)}
                      </Typography>
                    </MenuItem>
                  ))}
                </Select>
              ) : (
                <ToggleButtonGroup
                  size="small"
                  value={state.interval}
                  sx={{
                    padding: '4px',
                    borderRadius: '36px',
                    height: '40px',
                    boxSizing: 'border-box',
                    backgroundColor: 'grey.100',
                    border: 0,
                  }}
                  onChange={(_, value) => {
                    if (value !== null) {
                      setState({ interval: value });
                    }
                  }}
                  exclusive>
                  {recurringKeysList.map((x) => (
                    <ToggleButton
                      size="small"
                      key={x}
                      value={x}
                      sx={{
                        textTransform: 'capitalize',
                        padding: '5px 12px',
                        fontSize: '13px',
                        backgroundColor: ({ palette }) =>
                          x === state.interval
                            ? `${palette.background.default} !important`
                            : `${palette.grey[100]} !important`,
                        border: '0px',
                        '&.Mui-selected': {
                          borderRadius: '9999px !important',
                          border: '1px solid',
                          borderColor: 'divider',
                        },
                      }}>
                      {formatRecurring(recurring[x] as PriceRecurring, true, '', locale)}
                    </ToggleButton>
                  ))}
                </ToggleButtonGroup>
              )}
            </Box>
          )}
          {currencyList.length > 0 && !hideCurrency && (
            <Select
              value={currency?.id}
              onChange={(e) => setCurrency(currencyList.find((v) => v?.id === e.target.value))}
              size="small"
              sx={{ m: 1, minWidth: 180 }}>
              {currencyList.map((x) => (
                <MenuItem key={x?.id} value={x?.id}>
                  <Stack direction="row" alignItems="center" gap={1}>
                    <Avatar src={x?.logo} sx={{ width: 20, height: 20 }} alt={x?.symbol} />
                    <Typography fontSize="12px" color="text.secondary">
                      {x?.symbol}（{x?.method}）
                    </Typography>
                  </Stack>
                </MenuItem>
              ))}
            </Select>
          )}
        </Stack>
        <Stack
          flexWrap="wrap"
          direction="row"
          gap="20px"
          justifyContent={alignItems === 'center' ? 'center' : 'flex-start'}
          sx={{
            flex: '0 1 auto',
            pb: 2.5,
          }}
          className="price-table-wrap">
          {productList?.map((x: TPricingTableItem & { is_selected?: boolean; is_disabled?: boolean }) => {
            let action: string = x.subscription_data?.trial_period_days
              ? t('payment.checkout.try')
              : t('payment.checkout.subscription');
            if (mode === 'select') {
              action = x.is_selected ? t('payment.checkout.selected') : t('payment.checkout.select');
            }
            const [amount, unit] = formatPriceAmount(x.price, currency, x.product.unit_label).split('/');
            return (
              <Stack
                key={x?.price_id}
                padding={4}
                spacing={2}
                direction="column"
                alignItems="flex-start"
                className="price-table-item"
                justifyContent="flex-start"
                sx={{
                  cursor: 'pointer',
                  borderWidth: '1px',
                  borderStyle: 'solid',
                  borderColor: mode === 'select' && x.is_selected ? 'primary.main' : 'grey.100',
                  borderRadius: 2,
                  transition: 'border-color 0.3s ease 0s, box-shadow 0.3s ease 0s',
                  boxShadow: 2,
                  '&:hover': {
                    borderColor: mode === 'select' && x.is_selected ? 'primary.main' : 'grey.200',
                    boxShadow: 2,
                  },
                  width: {
                    xs: '100%',
                    md: '360px',
                  },
                  maxWidth: '360px',
                  minWidth: '300px',

                  padding: '20px',
                  position: 'relative',
                }}>
                <Box textAlign="center">
                  <Stack
                    direction="column"
                    justifyContent="center"
                    alignItems="flex-start"
                    spacing={1}
                    sx={{ gap: '12px' }}>
                    <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                      <Typography
                        color="text.secondary"
                        fontWeight={600}
                        sx={{
                          fontSize: '18px !important',
                          fontWeight: '600',
                        }}>
                        <TruncatedText text={x.product.name} maxLength={26} useWidth />
                      </Typography>
                      {x.is_highlight && (
                        <Chip
                          label={x.highlight_text}
                          color="primary"
                          size="small"
                          sx={{
                            position: 'absolute',
                            top: '20px',
                            right: '20px',
                          }}
                        />
                      )}
                    </Box>
                    <Typography
                      component="div"
                      sx={{
                        my: 0,
                        fontWeight: '700',
                        fontSize: '32px',
                        letterSpacing: '-0.03rem',
                        fontVariantNumeric: 'tabular-nums',
                        display: 'flex',
                        alignItems: 'baseline',
                        gap: '4px',
                        flexWrap: 'wrap',
                        lineHeight: 'normal',
                      }}>
                      {amount}
                      {unit ? (
                        <Typography
                          sx={{ fontSize: '16px', fontWeight: '400', color: 'text.secondary', textAlign: 'left' }}>
                          / {unit}
                        </Typography>
                      ) : (
                        ''
                      )}
                    </Typography>
                    <Typography
                      color="text.secondary"
                      sx={{
                        marginTop: '0px !important',
                        fontWeight: '400',
                        fontSize: '16px',
                        textAlign: 'left',
                      }}>
                      {x.product.description}
                    </Typography>
                  </Stack>
                </Box>
                {x.product.features.length > 0 && (
                  <Box sx={{ width: '100%' }}>
                    <List dense sx={{ display: 'flex', flexDirection: 'column', gap: '16px', padding: '0px' }}>
                      <Box
                        sx={{
                          width: '100%',
                          position: 'relative',
                          borderTop: '1px solid',
                          borderColor: 'divider',
                          boxSizing: 'border-box',
                          height: '1px',
                        }}
                      />
                      {x.product.features.map((f: any) => (
                        <ListItem key={f.name} disableGutters disablePadding sx={{ fontSize: '16px !important' }}>
                          <ListItemIcon sx={{ minWidth: 25, color: 'text.secondary', fontSize: '64px' }}>
                            <CheckOutlined
                              color="success"
                              fontSize="small"
                              sx={{
                                fontSize: '18px',
                                color: 'success.main',
                              }}
                            />
                          </ListItemIcon>
                          <ListItemText
                            sx={{
                              '.MuiListItemText-primary': {
                                fontSize: '16px',
                                color: 'text.primary',
                                fontWeight: '500',
                              },
                            }}
                            primary={f.name}
                          />
                        </ListItem>
                      ))}
                    </List>
                  </Box>
                )}
                <Subscribe x={x} action={action} onSelect={onSelect} currencyId={currency?.id} />
              </Stack>
            );
          })}
        </Stack>
      </Stack>
    </Root>
  );
}

function Subscribe({ x, action, onSelect, currencyId }: any) {
  const [state, setState] = useState({ loading: '', loaded: false });

  const handleSelect = async (priceId: string) => {
    try {
      setState({ loading: priceId, loaded: true });
      await onSelect(priceId, currencyId);
    } catch (err) {
      console.error(err);
      Toast.error(formatError(err));
    }
  };

  return (
    <LoadingButton
      fullWidth
      size="medium"
      variant="contained"
      color="primary"
      sx={{
        fontSize: '16px',
        padding: '10px 20px',
        lineHeight: '28px',
      }}
      loading={state.loading === x.price_id && !state.loaded}
      disabled={x.is_disabled}
      onClick={() => handleSelect(x.price_id)}>
      {action}
    </LoadingButton>
  );
}
