import { ChangeEvent } from 'react';
import { Alert, Box, CircularProgress, Stack, Typography } from '@mui/material';
import { useCreation, useMemoizedFn, useReactive, useRequest } from 'ahooks';
import { Icon } from '@iconify/react';
import AddRoundedIcon from '@iconify-icons/material-symbols/add-rounded';
import Switch from '@arcblock/ux/lib/Switch';
import Button from '@arcblock/ux/lib/Button';
import Toast from '@arcblock/ux/lib/Toast';
import { getWalletDid } from '@arcblock/ux/lib/SessionUser/libs/utils';
import { translate } from '@arcblock/ux/lib/Locale/util';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { AxiosError } from 'axios';
import DID from '@arcblock/ux/lib/DID';

import { translations } from '../libs/locales';
import WebhookItem from './webhook-item';
import { User, WebhookItemData } from '../../@types';
import { formatAxiosError } from '../libs/utils';
import { client } from '../../libs/client';

function NotificationItem({
  title = undefined,
  description = undefined,
  value,
  onChange,
  isMobile,
}: {
  title?: string;
  description?: React.ReactNode;
  value: boolean;
  onChange: (event: ChangeEvent<HTMLInputElement>) => void;
  isMobile: boolean;
}) {
  const handleClick = useMemoizedFn((event: React.MouseEvent) => {
    event.stopPropagation();
  });

  return (
    <Box
      sx={{
        display: 'flex',
        alignItems: 'center',
        gap: 1,
      }}>
      <Switch checked={value} size="small" onChange={onChange} />
      <Typography
        component="div"
        onClick={handleClick}
        sx={{
          color: 'text.primary',
          fontSize: 14,
          display: 'flex',
          flexWrap: isMobile ? 'wrap' : 'nowrap',
          columnGap: 1,
          flex: 1,
          whiteSpace: isMobile ? 'normal' : 'nowrap',
        }}>
        {title}
        {description}
      </Typography>
    </Box>
  );
}

export default function Notification({ user, isMobile }: { user: User; isMobile: boolean }) {
  const { locale } = useLocaleContext();
  const t = useMemoizedFn((key, data = {}) => {
    return translate(translations, key, locale, 'en', data);
  });
  const currentState = useReactive({
    showAdd: false,
  });

  const notificationConfigState = useRequest(
    async () => {
      const data = await client.user.getUserNotificationConfig();
      return data;
    },
    {
      refreshDeps: [user],
      loadingDelay: 300,
    }
  );
  const notifications = useCreation(() => {
    return {
      wallet: true,
      email: true,
      phone: false,
      push: true,
      ...(notificationConfigState?.data?.notifications || {}),
    };
  }, [notificationConfigState?.data?.notifications]);

  const webhooks = useCreation(() => {
    return notificationConfigState?.data?.webhooks || [];
  }, [notificationConfigState?.data?.webhooks]);

  const onSaveChanges = useMemoizedFn(async (values) => {
    try {
      await client.user.saveUserNotificationConfig(values);
      Toast.success(t('saveSuccess'));
      notificationConfigState.run();
    } catch (err) {
      Toast.error(formatAxiosError(err as AxiosError));
    }
  });

  const handleChangeSwitch = useMemoizedFn(async (channel, value) => {
    await onSaveChanges({
      notifications: {
        [channel]: value,
      },
    });
  });
  const handleTestWebhook = async (data: WebhookItemData) => {
    try {
      await client.user.testNotificationWebhook(data);
      Toast.success(t('webhookTested'));
    } catch (err) {
      Toast.error(formatAxiosError(err as AxiosError));
    }
  };
  const handleDeleteWebhook = useMemoizedFn(async (index) => {
    await onSaveChanges({
      webhooks: webhooks.filter((_: WebhookItemData, i: number) => i !== index),
    });
  });
  const handleEditWebhook = useMemoizedFn(async (index, webhook) => {
    await onSaveChanges({
      webhooks: webhooks.map((item: WebhookItemData, i: number) => (i === index ? webhook : item)),
    });
  });
  const handleAddWebhook = useMemoizedFn(async (webhook) => {
    await onSaveChanges({
      webhooks: [...webhooks, webhook],
    });
    currentState.showAdd = false;
  });

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

  if (notificationConfigState.loading || !notificationConfigState.data) {
    return (
      <Box
        sx={{
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
          height: '100px',
        }}>
        <CircularProgress />
      </Box>
    );
  }

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
      <Box
        sx={{
          display: 'flex',
          flexDirection: 'column',
          gap: 1,
          alignItems: 'start',
          '.MuiFormControlLabel-root': {
            gap: 1,
            m: 0,
            flexDirection: {
              xs: 'row-reverse',
              md: 'row',
            },
            width: {
              xs: '100%',
              md: 'unset',
            },
          },

          '.MuiSwitch-track': {
            borderRadius: '100vw',
          },
          '.MuiSwitch-thumb': {
            borderRadius: '100%',
          },
          '.MuiSwitch-root.MuiSwitch-sizeSmall': {
            height: '20px',
            width: '36px',
            '.MuiSwitch-thumb': {
              width: '16px',
              height: '16px',
            },
          },
        }}>
        <NotificationItem
          value={notifications.wallet}
          isMobile={isMobile}
          title={t('walletNotification')}
          onChange={(event: ChangeEvent<HTMLInputElement>) => handleChangeSwitch('wallet', event.target.checked)}
          description={
            getWalletDid(user) && (
              <DID
                did={getWalletDid(user)}
                showQrcode={false}
                showAvatar={!isMobile}
                copyable
                compact
                responsive
                locale={locale}
                startChars={isMobile ? 2 : 6}
              />
            )
          }
        />
        <NotificationItem
          value={notifications.email}
          isMobile={isMobile}
          onChange={(event: ChangeEvent<HTMLInputElement>) => handleChangeSwitch('email', event.target.checked)}
          title={t('emailNotification')}
          description={
            user?.email && (
              <Typography
                component="span"
                sx={{
                  color: 'text.secondary',
                  fontSize: 13,
                }}>
                {user?.email}
              </Typography>
            )
          }
        />
        <NotificationItem
          isMobile={isMobile}
          value={notifications.push}
          title={t('pushNotification')}
          onChange={(event: ChangeEvent<HTMLInputElement>) => handleChangeSwitch('push', event.target.checked)}
        />
        {/* TODO: @zhanghan 实现短信通知后展示此配置项 */}
        {/* <Switch
          disabled
          checked={notifications.phone}
          labelProps={{
            label: (
              <Typography
                color="text.primary"
                sx={{
                  fontSize: 14,
                  display: 'flex',
                  flexFlow: 'wrap',
                  columnGap: 1,
                  flex: 1,
                }}>
                {t('phoneNotification')}
                {user?.phone && (
                  <Typography component="span" color="text.secondary" fontSize={13}>
                    {user?.phone}
                  </Typography>
                )}
              </Typography>
            ),
          }}
          size="small"
          onChange={(event: ChangeEvent<HTMLInputElement>) => handleChangeSwitch('phone', event.target.checked)}
        /> */}
      </Box>
      <Stack
        spacing={1.5}
        useFlexGap
        direction="column"
        sx={{
          alignItems: 'start',
        }}>
        {webhooks.map((item: WebhookItemData, index: number) => (
          <WebhookItem
            // eslint-disable-next-line react/no-array-index-key
            key={`${index}_${item.url}`}
            onTest={handleTestWebhook}
            onDelete={() => handleDeleteWebhook(index)}
            onSave={(...args) => handleEditWebhook(index, ...args)}
            type={item.type}
            url={item.url}
            edit={false}
          />
        ))}
        {currentState.showAdd && (
          <WebhookItem
            key="add"
            onTest={handleTestWebhook}
            onCancel={() => {
              currentState.showAdd = false;
            }}
            onSave={(...args) => handleAddWebhook(...args)}
            edit
          />
        )}

        <Button
          variant="outlined"
          size="small"
          sx={{
            color: 'text.primary',
            borderColor: 'divider',
            '&:hover': {
              borderColor: 'divider',
            },
            py: 0.5,
            borderRadius: 1,
          }}
          startIcon={<Icon icon={AddRoundedIcon} />}
          onClick={() => {
            currentState.showAdd = true;
          }}>
          {t('addWebhook')}
        </Button>
      </Stack>
    </Box>
  );
}
