import { memo, useRef } from 'react';
import { useBrowser } from '@arcblock/react-hooks';
import { Backdrop, Box, Dialog, DialogContent, Drawer, SwipeableDrawer, SxProps, useMediaQuery } from '@mui/material';
import { useCreation, useDebounce } from 'ahooks';
import colorConvert from 'color-convert';
import { getDIDMotifInfo } from '@arcblock/did-motif';
import noop from 'lodash/noop';

import { useTheme } from '../Theme';
import { mergeSx } from '../Util/style';
import { getDIDColor, hexToRgba, isEthereumDid } from '../Util';
import DIDConnectFooter from './did-connect-footer';

// eslint-disable-next-line react/require-default-props
const BackdropWrap = memo(({ ref, ...backdropProps }: { ref?: React.Ref<unknown> }) => {
  return (
    <Backdrop
      open
      ref={ref}
      style={{
        backgroundColor: 'rgba(0, 0, 0, 0.6)',
        backdropFilter: 'blur(3px)',
        touchAction: 'none',
      }}
      {...backdropProps}
      key="background"
    />
  );
});

export default function DIDConnectContainer({
  open = false,
  popup = false,
  hideCloseButton = false,
  children,
  appPid = undefined,
  slotProps = undefined,
  onClose = noop,
  keepMounted = false,
}: {
  // 是否弹出显示, true 表示在 Dialog 中渲染, 并可以通过 open/onClose 控制 dialog 的显示/隐藏, false 表示直接渲染原内容
  popup?: boolean;
  open?: boolean;
  hideCloseButton?: boolean;
  children: React.ReactNode;
  onClose?: () => void;
  appPid?: string;
  slotProps?: {
    footer?: {
      sx?: SxProps;
    };
    containerPage?: {
      sx?: SxProps;
    };
    containerDrawer?: {
      sx?: SxProps;
    };
    containerDialog?: {
      sx?: SxProps;
    };
  };
  keepMounted?: boolean;
}) {
  const color = useCreation(() => {
    const did = appPid || window.blocklet.appPid;
    const isEthDid = isEthereumDid(did);
    const didMotifInfo = isEthDid ? undefined : getDIDMotifInfo(did);
    if (isEthDid) {
      return getDIDColor(did);
    }

    return didMotifInfo.color;
  }, []);

  const drawerDragger = useRef(null);
  const browser = useBrowser();
  // 屏宽小于 sm 且在 mobile 设备中全屏显示 dialog (PC 端屏宽小于 sm 的情况正常弹窗, 不全屏显示)
  const matchSm = useMediaQuery('(max-width:640px)');
  let openVariant = 'page';
  if (popup) {
    openVariant = 'dialog';
    if (matchSm && browser.mobile.any) {
      openVariant = 'drawer';
    }
  }

  const theme = useTheme();

  const leavingScreenDelay = theme?.transitions?.duration?.leavingScreen || 500; // 默认值是 195
  const debouncedOpen = useDebounce(open, {
    wait: leavingScreenDelay,
  });

  // eslint-disable-next-line no-unused-vars
  const handleOnClose = (e: React.MouseEvent<HTMLElement>, reason: string) => {
    if (['backdropClick', 'escapeKeyDown'].includes(reason)) return;
    onClose();
  };

  const showModal = debouncedOpen || open || keepMounted;

  const DrawerComponent = hideCloseButton ? Drawer : SwipeableDrawer;

  const hslColor = colorConvert.hex.hsl(color);

  const [h, s, l] = hslColor;
  const percentageList = [0, 30, 60, 30, 0, 30, 60, 30];
  const maxPercentage = Math.max(...percentageList);
  const minPercentage = Math.min(...percentageList);
  let useAlpha = false;
  if ((l * (100 + maxPercentage)) / 100 > 100 || (l * (100 + minPercentage)) / 100 < 0) {
    // 超出范围，使用 alpha 通道变化
    useAlpha = true;
  }
  const colorList = percentageList.map((percentageItem) => {
    let finalL = (l * (100 + percentageItem)) / 100;
    let finalAlpha = 0.6;
    if (useAlpha) {
      finalAlpha = (0.5 * (100 + percentageItem)) / 100;
    } else {
      finalL = (l * (100 + percentageItem)) / 100;
    }
    return `hsla(${h}, ${s}%, ${finalL}%, ${finalAlpha})`;
  });
  const background = `linear-gradient(45deg, ${colorList.join(', ')})`;
  const colorListGlow = percentageList.map((percentageItem) => {
    let finalL = (l * (100 + percentageItem)) / 100;
    let finalAlpha = 0.2;
    if (useAlpha) {
      finalAlpha = (0.3 * (100 + percentageItem)) / 100;
    } else {
      finalL = (l * (100 + percentageItem)) / 100;
    }
    return `hsla(${h}, ${s}%, ${finalL}%, ${finalAlpha})`;
  });

  const backgroundGlow = `linear-gradient(45deg, ${colorListGlow.join(', ')})`;

  const glowStyle = open
    ? {
        overflow: 'visible',
        '&::before, &::after': {
          content: '""',
          position: 'absolute',
          top: '-3px',
          right: '-3px',
          bottom: '-3px',
          left: '-3px',
          background,
          backgroundSize: '300% 300%',
          backgroundRepeat: 'no-repeat',
          animation: 'glowRotate 10s linear infinite',
          borderRadius: '14px !important',
          zIndex: 0,
        },
        '&::after': {
          background: backgroundGlow,
          filter: 'blur(15px)',
        },

        '@keyframes glowRotate': {
          '0%': {
            backgroundPosition: '0 0',
          },
          '50%': {
            backgroundPosition: '100% 0',
          },
          '100%': {
            backgroundPosition: '0 0',
          },
        },
      }
    : {};

  if (openVariant === 'page') {
    return (
      <Box
        className="did-connect__container-page"
        sx={mergeSx(
          {
            borderRadius: 1,
            position: 'relative',
            zIndex: 1,
            backgroundColor: 'background.default',
          },
          glowStyle,
          slotProps?.containerPage?.sx
        )}>
        <Box
          sx={{
            border: `1px solid ${hexToRgba(color, 0.1)}`,
            m: '-1px',
            position: 'relative',
            borderRadius: '12px',
            zIndex: 2,
            overflow: 'hidden',
            backgroundColor: 'background.default',
          }}>
          {children}
          <DIDConnectFooter currentAppColor={color} sx={mergeSx({ mx: 0 }, slotProps?.footer?.sx)} />
        </Box>
      </Box>
    );
  }

  if (openVariant === 'drawer') {
    return (
      <DrawerComponent
        className="did-connect__container-drawer"
        disableSwipeToOpen
        open={open}
        anchor="bottom"
        drawerDragger={drawerDragger.current}
        // @ts-ignore
        onClose={handleOnClose}
        slots={{
          backdrop: BackdropWrap,
        }}
        PaperProps={{
          sx: mergeSx(
            {
              backgroundColor: 'background.default',
              borderRadius: 3, // 保持跟 DID Wallet 一致
              borderBottomLeftRadius: 0,
              borderBottomRightRadius: 0,
              p: '2px',
              '.did-connect__root': {
                backgroundColor: 'transparent',
              },
              overflow: 'hidden',
              animation: open ? 'glowBreathe 7s linear infinite' : 'none',
              '@keyframes glowBreathe': {
                '0%, 100%': {
                  boxShadow: `
                    inset 0 0 7px ${hexToRgba(color, 0.3)},
                    inset 0 0 12px ${hexToRgba(color, 0.3)}`,
                },
                '50%': {
                  boxShadow: `
                    inset 0 0 18px ${hexToRgba(color, 0.7)},
                    inset 0 0 24px ${hexToRgba(color, 0.5)}`,
                },
              },
            },
            slotProps?.containerDrawer?.sx
          ),
        }}>
        {hideCloseButton ? null : (
          <Box
            ref={drawerDragger}
            sx={{
              px: 1,
              pt: 2,
              m: 'auto',
              mt: -1,
              mb: -2,
              zIndex: 2,
            }}>
            <Box
              sx={{
                width: '48px',
                height: '4px',
                borderRadius: '100vw',
                backgroundColor: 'rgba(0, 0, 0, 0.2)',
              }}
            />
          </Box>
        )}
        <Box
          sx={{
            touchAction: 'none',
            maxWidth: '100%',
            width: 500,
            height: 'auto',
            backgroundColor: 'background.default',
          }}>
          {/* HACK: 由于 MUI 文档中描述 使用 keepMounted: false 可能会造成问题，所以采用下面的方案进行 HACK */}
          {/* https://mui.com/material-ui/react-drawer/#keep-mounted */}
          {showModal ? children : null}
          <DIDConnectFooter currentAppColor={color} sx={mergeSx({ mx: 0 }, slotProps?.footer?.sx)} />
        </Box>
      </DrawerComponent>
    );
  }

  return (
    <Dialog
      open={open}
      slots={{
        backdrop: BackdropWrap,
      }}
      keepMounted={keepMounted}
      className="did-connect__container-dialog"
      onClose={handleOnClose}
      PaperProps={{
        sx: mergeSx(
          {
            // 避免样式被 server 中的定义覆盖
            '&.MuiPaper-rounded': {
              borderRadius: '12px !important',
            },
            position: 'relative',
            backgroundColor: 'background.default',
          },
          glowStyle,
          slotProps?.containerDialog?.sx
        ),
      }}>
      <DialogContent
        sx={{
          maxWidth: 'calc(100vw - 18px)',
          maxHeight: 'calc(100vh - 18px)',
          p: '0px !important',
          height: 'auto',
          borderRadius: '12px !important',
          zIndex: 1,
          backgroundColor: 'background.default',
        }}>
        {showModal ? children : null}
        <DIDConnectFooter currentAppColor={color} sx={mergeSx({ mx: 0 }, slotProps?.footer?.sx)} />
      </DialogContent>
    </Dialog>
  );
}
