import type { FC } from 'react';
import {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';

import { useWallet } from '@solana/wallet-adapter-react';

import { useWalletModal } from '../hooks';
import {
  Button,
  type ButtonProps,
} from './Button';
import { WalletIcon } from './WalletIcon';
import { WalletModalButton } from './WalletModalButton';

export const WalletMultiButton: FC<ButtonProps> = ({
  children,
  listMenuItems,
  ...props
}) => {
  const { publicKey, wallet, disconnect } = useWallet()
  const { trans } = useWalletModal()
  const [copied, setCopied] = useState(false)
  const [active, setActive] = useState(false)
  const ref = useRef<HTMLUListElement>(null)

  const base58 = useMemo(() => publicKey?.toBase58(), [publicKey])
  const content = useMemo(() => {
    if (children) return children
    if (!wallet || !base58) return null
    return base58.slice(0, 4) + '...' + base58.slice(-4)
  }, [children, wallet, base58])

  const copyAddress = useCallback(async () => {
    if (base58) {
      await navigator.clipboard.writeText(base58)
      setCopied(true)
      setTimeout(() => setCopied(false), 400)
    }
  }, [base58])

  const openDropdown = useCallback(() => {
    setActive(true)
  }, [])

  const closeDropdown = useCallback(() => {
    setActive(false)
  }, [])

  useEffect(() => {
    const listener = (event: MouseEvent | TouchEvent) => {
      const node = ref.current

      // Do nothing if clicking dropdown or its descendants
      if (!node || node.contains(event.target as Node)) return

      closeDropdown()
    }

    document.addEventListener('mousedown', listener)
    document.addEventListener('touchstart', listener)

    return () => {
      document.removeEventListener('mousedown', listener)
      document.removeEventListener('touchstart', listener)
    }
  }, [ref, closeDropdown])

  if (!wallet || !base58)
    return (
      <div className="wallet-adapter-button-wrap">
        <WalletModalButton {...props}>{children}</WalletModalButton>
      </div>
    )

  return (
    <div className="wallet-adapter-button-wrap">
      <Button
        aria-expanded={active}
        className="wallet-adapter-button-trigger"
        style={{ pointerEvents: active ? 'none' : 'auto', ...props.style }}
        onClick={openDropdown}
        beginIcon={<WalletIcon wallet={wallet} />}
        {...props}
      >
        <span className="wallet-adapter-button-content">{content}</span>
      </Button>
      <ul
        aria-label="dropdown-list"
        className={`wallet-adapter-dropdown-list ${
          active && 'wallet-adapter-dropdown-list-active'
        }`}
        ref={ref}
        role="menu"
      >
        <li onClick={copyAddress} role="menuitem">
          {copied ? trans.copied : trans.copy_address}
        </li>
        {listMenuItems}
        <li onClick={disconnect} role="menuitem">
          {trans.disconnect}
        </li>
      </ul>
    </div>
  )
}
