import { useRef } from 'react';
import PropTypes from 'prop-types';
import { Portal, Typography, CircularProgress, useMediaQuery } from '@mui/material';

import Avatar from '../Avatar';
import Icon from '../Icon';
import Button from '../Button';
import Img from '../Img';
import { useTheme, styled } from '../Theme';

/**
 * 美化数字 1000-->1k
 * @param {*} _size
 * @param {*} digits
 * @returns
 */
function prettySize(_size, digits = 1) {
  let size = _size;
  const list = ['', 'k', 'm', 'b'];
  let index = 0;
  while (size > 1000 && index < list.length - 1) {
    size = (size / 1000).toFixed(digits);
    index += 1;
  }
  return _size && `${size}${list[index]}`;
}

const Div = styled('div')`
  &.arcblock-blocklet {
    padding: 0 16px;
    background: ${(props) => props.theme.palette.common.white};
    overflow: hidden;
    box-shadow: 0px 0px 8px #f0f0f0;
    &:hover {
      box-shadow: 0px 2px 12px #f0f0f0;
    }
  }
  .arcblock-blocklet__content {
    padding: 16px 0 0 0;
  }
  .arcblock-blocklet__content--main {
    display: flex;
    align-items: center;
    cursor: pointer;
  }
  .arcblock-blocklet__content--body {
    overflow: hidden;
    flex: 1;
    display: flex;
    align-items: flex-start;
  }
  .arcblock-blocklet__addons {
    padding: 16px 0;
  }
  .arcblock-blocklet__cover {
    width: 80px;
    height: 80px;
    margin-right: 12px;
    overflow: hidden;
    border-radius: 12px;
    /* see: https://stackoverflow.com/questions/49066011/overflow-hidden-with-border-radius-not-working-on-safari */
    transform: translateZ(0);
  }
  .arcblock-blocklet__button--hover {
    &:not(.Mui-disabled) {
      position: relative;
      z-index: 1;
      &::before {
        content: '';
        position: absolute;
        height: 100%;
        width: 100%;
        left: 0;
        top: 0;
        transition: opacity 0.3s;
      }
      &:hover::before {
        opacity: 0;
      }
      &::after {
        content: '';
        position: absolute;
        height: 100%;
        width: 100%;
        top: 0;
        left: 0;
        background-color: ${(props) => props.theme.palette.primary.main};
        transform: scale(0.1);
        opacity: 0;
        z-index: -1;
        transition:
          transform 0.3s,
          opacity 0.3s,
          background-color 0.3s;
      }
      &:hover::after {
        opacity: 1;
        transform-origin: center;
        transform: scale(1);
      }
    }

    &:not(.Mui-disabled) {
      background-color: transparent !important;
      color: ${(props) => props.theme.palette.primary.main};
    }
    &:not(.Mui-disabled) {
      &:hover {
        color: ${(props) => props.theme.palette.common.white};
      }
    }
  }
  .arcblock-blocklet__info {
    flex: 1;
    overflow: hidden;
    .arcblock-blocklet__button {
      margin-top: 16px;
      display: inline-block;
    }
  }
  .arcblock-blocklet__title {
    margin: 0;
    font-size: 18px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .arcblock-blocklet__describe {
    margin: 0 0 2px 0;
    color: #999;
    font-size: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .arcblock-blocklet__addons {
    display: flex;
    justify-content: space-between;
    color: #999;
    font-size: 14px;
    position: relative;
  }
  .arcblock-blocklet__addons--item {
    white-space: nowrap;
  }
  &.arcblock-blocklet--size-md {
    &:hover {
      position: relative;
    }
    .arcblock-blocklet__title {
      height: 2.3em;
      margin-bottom: 3px;
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      overflow: hidden;
      text-overflow: initial;
      white-space: initial;
      word-break: break-all;
    }
    .arcblock-blocklet__describe {
      white-space: normal;
      height: 2.86em;
    }
    .arcblock-blocklet__button {
      margin-top: 5px;
    }
  }
  &.arcblock-blocklet--size-sm,
  &.arcblock-blocklet--size-xs {
    .arcblock-blocklet__cover {
      width: 40px;
      height: 40px;
      border-radius: 6px;
    }
    .arcblock-blocklet__content {
      padding: 16px 0;
    }
    .arcblock-blocklet__addons {
      padding: 8px 0;
      .arcblock-blocklet__addons--item {
        font-size: 12px;
      }
    }
  }
  &.arcblock-blocklet--size-xs {
    .arcblock-blocklet__addons {
      display: none !important;
    }
  }
`;
function BlockletIcon({ name }) {
  return <Icon name={name} color="inherit" size={15} style={{ marginRight: 8 }} />;
}
BlockletIcon.propTypes = {
  name: PropTypes.string.isRequired,
};

/**
 * BlockletNFT 组件
 * @typedef {{
 *  title: string;
 *  description?: string;
 *  cover?: string;
 *  did?: string;
 *  isStickyButton?: false | true;
 *  buttonText?: string;
 *  buttonDisabled?: false | true;
 *  buttonLoading?: false | true;
 *  button?: JSX.Element;
 *  addons?: Array<any>;
 *  size?: 'xs' | 'sm' | 'md' | 'auto';
 *  onButtonClick?: Function;
 *  onMainClick?: Function;
 *  className?: string;
 *  scaleClickZone?: number;
 * } & import('react').ComponentPropsWithoutRef<"div"> } BlockletNFTProps
 */

/**
 * BlockletNFT 组件
 * @param {BlockletNFTProps} props
 * @returns {JSX.Element}
 */
export default function BlockletNFT({
  title,
  did = undefined,
  description = null,
  cover = null,
  size = 'auto',
  addons = [],
  button = null,
  buttonText = 'Install',
  buttonDisabled = false,
  buttonLoading = false,
  isStickyButton = false,
  onButtonClick = null,
  onMainClick = null,
  className = null,
  scaleClickZone = 1.5,
  ...rest
}) {
  const wrapHandler =
    (handler, stopFn = () => false) =>
    (e, ...args) => {
      if (stopFn()) {
        e.preventDefault();
        e.stopPropagation();
      } else if (handler instanceof Function) {
        e.preventDefault();
        e.stopPropagation();
        handler(...args);
      }
    };
  const _onButtonClick = wrapHandler(onButtonClick, () => {
    // stop click while custom button or buttonDisabled or buttondLoading
    if (button || buttonDisabled || buttonLoading) {
      return true;
    }
    return false;
  });
  const _onMainClick = wrapHandler(onMainClick);

  const theme = useTheme();
  const isDownSm = useMediaQuery(theme.breakpoints.down('md'));
  const isDownMd = useMediaQuery(theme.breakpoints.down('lg'));
  const isUpLg = useMediaQuery(theme.breakpoints.up('lg'));

  // If size is auto, need calculate actual size according to screen size
  // eslint-disable-next-line no-nested-ternary
  const actualSize = size === 'auto' ? (isDownSm ? 'xs' : isDownMd ? 'sm' : 'md') : size;
  // eslint-disable-next-line no-nested-ternary
  const didAvatarSize = size === 'auto' ? (isUpLg ? 80 : 40) : size === 'md' ? 80 : 40;
  const container = useRef(null);

  return (
    <Div
      {...rest}
      scaleClickZone={scaleClickZone}
      className={`${className} arcblock-blocklet arcblock-blocklet--size-${actualSize}`}>
      <div className="arcblock-blocklet__content">
        <div className="arcblock-blocklet__content--main" onClick={_onMainClick} ref={container}>
          <div className="arcblock-blocklet__content--body">
            {cover ? (
              <div className="arcblock-blocklet__cover">
                <Img src={cover} />
              </div>
            ) : (
              did && (
                <div className="arcblock-blocklet__cover">
                  <Avatar did={did} size={didAvatarSize} />
                </div>
              )
            )}
            <div className="arcblock-blocklet__info">
              <Typography component="h3" variant="h3" className="arcblock-blocklet__title" title={title}>
                {title}
              </Typography>
              {description && (
                <Typography component="div" variant="body2" className="arcblock-blocklet__describe" title={description}>
                  {description}
                </Typography>
              )}
              {['md', 'sm', 'xs'].includes(actualSize) && (
                <Portal container={container.current} disablePortal={actualSize === 'md'}>
                  <div
                    className="arcblock-blocklet__button"
                    onClick={_onButtonClick}
                    style={{ display: isStickyButton ? 'block' : '' }}>
                    {button ||
                      (onButtonClick && (
                        <Button
                          className="arcblock-blocklet__button--hover"
                          variant="outlined"
                          color="primary"
                          size="small"
                          disabled={buttonDisabled || buttonLoading}
                          style={
                            actualSize === 'md'
                              ? { padding: '3px 20px', fontSize: '14px' }
                              : { padding: '3px 15px', minWidth: '54px', fontSize: '13px' }
                          }>
                          {buttonLoading && (
                            <CircularProgress
                              size={actualSize === 'md' ? 15 : 13}
                              style={{ marginRight: 3, color: 'inherit' }}
                            />
                          )}
                          {buttonText}
                        </Button>
                      ))}
                  </div>
                </Portal>
              )}
            </div>
          </div>
        </div>
      </div>
      <div className="arcblock-blocklet__addons">
        {addons.map((item, index) => (
          <Typography
            component="span"
            variant="caption"
            className="arcblock-blocklet__addons--item"
            // eslint-disable-next-line react/no-array-index-key
            key={index}
            title={item.title}>
            {item.empty ? null : (
              <>
                <BlockletIcon name={item.icon} />
                {item.pretty ? prettySize(item.value) : item.value}
              </>
            )}
          </Typography>
        ))}
      </div>
    </Div>
  );
}
BlockletNFT.propTypes = {
  title: PropTypes.string.isRequired,
  did: PropTypes.string,
  isStickyButton: PropTypes.bool,
  description: PropTypes.string,
  cover: PropTypes.string,
  buttonText: PropTypes.string,
  buttonDisabled: PropTypes.bool,
  buttonLoading: PropTypes.bool,
  button: PropTypes.element,
  addons: PropTypes.arrayOf(PropTypes.object),
  size: PropTypes.oneOf(['xs', 'sm', 'md', 'auto']),
  onButtonClick: PropTypes.func,
  onMainClick: PropTypes.func,
  className: PropTypes.string,
  scaleClickZone: PropTypes.number,
};
