import { getDIDMotifInfo } from '@arcblock/did-motif';
import { types } from '@ocap/mcrypto';
import QRCode from 'qrcode.react';
import { Icon } from '@iconify/react';
import IconQrCode from '@iconify-icons/material-symbols/qr-code-rounded';
import { Box, Dialog, DialogContent, ModalProps, Typography } from '@mui/material';
import { useCreation, useMemoizedFn } from 'ahooks';
import { useImperativeHandle, useRef, useState } from 'react';
import { toAddress } from '@arcblock/did';
import noop from 'lodash/noop';

import Address, { IDidAddressWrapper } from '../Address';
import Avatar from '../Avatar';
import { DID_PREFIX } from '../Util/constant';

import { HTMLDidAddressElement } from '../Address/did-address';
import { translate } from '../Locale/util';
import { getDIDColor, isEthereumDid } from '../Util';

const translations = {
  en: {
    scanQrcode: 'Scan with DID Wallet to view the {role}',
    download: 'Download',
    downloadTips: "Don't have DID Wallet ?",
  },
  zh: {
    scanQrcode: '使用 DID Wallet 扫码查看该 {role}',
    download: '下载',
    downloadTips: '没有 DID Wallet ？',
  },
};

const DEFAULT_CHAIN_ID = 'xenon-2020-01-15';

const CHAIN_ID_MAP: Record<string, string> = {
  main: DEFAULT_CHAIN_ID,
  'main.abtnetwork.io': DEFAULT_CHAIN_ID,
  'beta.abtnetwork.io': 'beta',
};

const getFontColor = (did: string, didMotifInfo: any, isEthDid: boolean) => {
  if (isEthDid) {
    return getDIDColor(did);
  }

  return didMotifInfo.color;
};

const isSquareMotif = (roleType: number) => {
  const roles: Record<number, boolean> = {
    0: true, // ACCOUNT
    6: true, // ASSET
    17: true, // TOKEN
  };
  return !roles[roleType];
};

const getRoleName = (roleType: number) => {
  if (roleType === types.RoleType.ROLE_ANY) {
    return 'DID';
  }

  const [roleName] = Object.entries(types.RoleType).find((item) => item[1] === roleType) || [];
  if (roleName) {
    // UpperCase first word, example:
    // ROLE_ACCOUNT -> Account
    // ROLE_APPLICATION -> Application
    return roleName.toLowerCase().replace(/role_(\S)/g, (_, $1) => $1.toUpperCase());
  }

  return 'DID';
};

const getAvatarSize = (didMotifInfo: any, isEthDid: boolean, size: number) => {
  if (isEthDid) {
    return size * 0.75;
  }
  if (isSquareMotif(didMotifInfo.roleType)) {
    return size * 0.75;
  }
  return size;
};

function useDIDInfo({ did, showAvatar }: { did: string; showAvatar?: boolean }) {
  const isEthDid = isEthereumDid(did);
  const didMotifInfo = isEthDid ? undefined : getDIDMotifInfo(did);
  const content = useCreation(() => {
    if (isEthDid) {
      return did;
    }
    return `${DID_PREFIX}${did}`;
  }, [did, isEthDid]);

  const getPrepend = useMemoizedFn((avatarSize: number, keyPrefix: string) => [
    <span
      key={`${keyPrefix}-prefix-did-${avatarSize}`}
      style={{ flex: '0 0 auto', color: getFontColor(did, didMotifInfo, isEthDid) }}>
      DID:
    </span>,
    <span key={`${keyPrefix}-prefix-abt-${avatarSize}`} className="did-address-text">
      {isEthDid ? 'ETH' : 'ABT'}:
    </span>,
    showAvatar && (
      <Avatar
        key={`${keyPrefix}-avatar-${avatarSize}`}
        src=""
        did={did}
        size={getAvatarSize(didMotifInfo, isEthDid, avatarSize || 18)}
        style={{ display: 'inline-flex', alignItems: 'center', marginLeft: 2, marginRight: 4 }}
        blockiesPadding={false}
        className="did-address-avatar"
        sx={{ flexShrink: 0 }}
      />
    ),
  ]);

  return {
    isEthDid,
    didMotifInfo,
    content,
    getPrepend,
  };
}

interface DIDOwnProps {
  did: string;
  chainId?: string;
  roleType?: number;
  showAvatar?: true | false;
  showQrcode?: false | true;
}

export interface DIDProps extends DIDOwnProps, Omit<IDidAddressWrapper, 'ref'> {}

export interface HTMLDIDElement extends HTMLDidAddressElement {
  openQRCode: () => void;
  closeQRCode: () => void;
}

export function DID({
  ref = undefined,
  ...props
}: DIDProps & {
  ref?: React.Ref<unknown>;
}) {
  const {
    did: didAddress,
    chainId,
    roleType,
    showAvatar = true,
    showQrcode = false,
    locale = 'en',
    size = 0,
    component = 'span',
    copyable = true,
    responsive = true,
    showCopyButtonInTooltip = false,
    inline = false,
    append = null,
    compact = false,
    startChars = 6,
    endChars = 6,
    style,
    className,
    sx,
  } = props;
  const did = toAddress(didAddress);

  const rest = {
    size,
    component,
    copyable,
    responsive,
    showCopyButtonInTooltip,
    inline,
    append,
    compact,
    startChars,
    endChars,
    style,
    className,
    sx,
  };

  const addressRef = useRef<any>(null);
  const { content, getPrepend } = useDIDInfo({ did, showAvatar });
  const [open, setOpen] = useState(false);

  const closeQrCode = useMemoizedFn(() => {
    setOpen(false);
  });
  const openQrCode = useMemoizedFn((e) => {
    e.stopPropagation();
    e.preventDefault();
    setOpen(true);
  });

  useImperativeHandle(ref, () => {
    return new Proxy(
      {
        openQRCode: () => setOpen(true),
        closeQRCode: () => setOpen(false),
      },
      {
        get(target: any, key: string) {
          return target[key] || addressRef?.current?.[key];
        },
      }
    );
  });

  return (
    <>
      <Address
        key="address"
        locale={locale}
        content={content}
        {...rest}
        ref={addressRef}
        prepend={getPrepend(rest.size, 'address')}
        append={
          <>
            {showQrcode ? (
              <Box
                id="did-qrcode-button"
                component={Icon}
                icon={IconQrCode}
                onClick={openQrCode}
                sx={{
                  flexShrink: 0,
                  cursor: 'pointer',
                  ml: 0.5,
                  color: 'text.secondary',
                }}
              />
            ) : null}
            {rest.append}
          </>
        }>
        {did}
      </Address>
      <DIDDialog
        did={did}
        chainId={chainId}
        roleType={roleType}
        showAvatar={showAvatar}
        open={open}
        onClose={closeQrCode}
        {...rest}
      />
    </>
  );
}

export interface DIDDialogProps extends DIDProps {
  // DialogProps
  open: boolean;
  fullScreen?: false | true;
  fullWidth?: false | true;
  scroll?: 'body' | 'paper';
  onClose?: ModalProps['onClose'];
}
export function DIDDialog({
  did,
  chainId = undefined,
  roleType = undefined,
  showAvatar = true,
  // DialogProps
  open,
  fullScreen = false,
  fullWidth = false,
  scroll = 'paper',
  onClose = noop,
  // AddressProps
  locale = 'en',
  ...rest
}: DIDDialogProps) {
  const t = useMemoizedFn((key, data = {}) => {
    return translate(translations, key, locale, 'en', data);
  });

  const { isEthDid, content, didMotifInfo, getPrepend } = useDIDInfo({ did, showAvatar });

  const downloadUrl = useCreation(() => {
    if (['zh', 'en'].includes(locale)) {
      return `https://www.didwallet.io/${locale}`;
    }
    return 'https://www.didwallet.io/en';
  }, [locale]);

  const downloadTips = useCreation(() => {
    return (
      <>
        {t('downloadTips')}{' '}
        <Box
          component="a"
          href={downloadUrl}
          target="_blank"
          rel="noreferrer"
          sx={{
            color: 'secondary.main',
            textDecoration: 'none',
            '&:hover': {
              textDecoration: 'underline',
            },
          }}>
          {t('download')}
        </Box>
      </>
    );
  }, [downloadUrl]);

  const _chainId = useCreation(() => {
    if (chainId) {
      return CHAIN_ID_MAP[chainId] || chainId;
    }

    // 以太坊 DID 使用默认chainId '1'
    if (isEthDid) return '1';

    // 解析 chainHost 并获取对应的chainId
    try {
      const chainHostUrl = (window as any).blocklet?.CHAIN_HOST;
      const chainHost = new URL(chainHostUrl).hostname;
      if (chainHost) {
        return CHAIN_ID_MAP[chainHost] || DEFAULT_CHAIN_ID;
      }
    } catch (error) {
      console.warn('Failed to parse chainHost:', error);
    }
    return DEFAULT_CHAIN_ID;
  }, [isEthDid, chainId]);

  const qrCodeLink = useCreation(() => {
    if (isEthDid) {
      return `ethereum:abtwallet.io/i?address=${content}&action=didRecognize&chainID=${_chainId}`;
    }
    return `abt://abtwallet.io/i?did=${content}&action=didRecognize&chainID=${_chainId}`;
  }, [content, isEthDid, _chainId]);

  return (
    <Dialog
      open={open}
      onClose={onClose}
      fullScreen={fullScreen}
      fullWidth={fullWidth}
      scroll={scroll}
      maxWidth="sm"
      PaperProps={{
        sx: {
          boxShadow: 'none',
          borderRadius: '12px',
        },
      }}>
      {/* @ts-ignore */}
      <DialogContent align="center" sx={{ p: 3 }}>
        <Typography sx={{ mb: 2, fontWeight: 500, fontSize: 18 }}>
          {t('scanQrcode', { role: getRoleName(roleType || didMotifInfo?.roleType) })}
        </Typography>
        <QRCode
          // eslint-disable-next-line max-len
          value={qrCodeLink}
          size={256}
          renderAs="svg"
          level="M"
        />
        <Box sx={{ mt: 1.5, textAlign: 'center' }}>
          <Address
            key="dialog-address"
            locale={locale}
            content={content}
            prepend={getPrepend(16, 'dialog')}
            {...rest}
            size={16}
            copyable>
            {did}
          </Address>
        </Box>
        <Typography
          variant="body2"
          sx={{
            color: 'text.secondary',
            fontSize: '12px',
            mt: 1,
          }}>
          {downloadTips}
        </Typography>
      </DialogContent>
    </Dialog>
  );
}

export default DID;
