import React, { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';

import type { AppToken } from '../../shared/types';
import { useTokenImageUrl } from '../shared/tokens/useTokenImageUrl';

import styles from './SceneEditorApp.module.css';

const TOKEN_DND_MIME = 'application/x-dnd-app-token-id';

type Props = {
  token: AppToken;
  onEdit: () => void;
  onDelete: () => void;
};

export function TokenTile({ token, onEdit, onDelete }: Props) {
  const url = useTokenImageUrl(token.id);
  const menuBtnRef = useRef<HTMLButtonElement | null>(null);
  const menuRef = useRef<HTMLDivElement | null>(null);
  const [menu, setMenu] = useState<{ x: number; y: number } | null>(null);

  useEffect(() => {
    if (!menu) return;
    const onPointerDown = (e: PointerEvent) => {
      const t = e.target;
      if (!(t instanceof Node)) return;
      if (menuBtnRef.current?.contains(t)) return;
      if (menuRef.current?.contains(t)) return;
      setMenu(null);
    };
    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') setMenu(null);
    };
    window.addEventListener('pointerdown', onPointerDown, true);
    window.addEventListener('keydown', onKey);
    return () => {
      window.removeEventListener('pointerdown', onPointerDown, true);
      window.removeEventListener('keydown', onKey);
    };
  }, [menu]);

  const openMenu = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    const pad = 8;
    const menuW = 160;
    const menuH = 84;
    const x = Math.max(pad, Math.min(e.clientX, window.innerWidth - menuW - pad));
    const y = Math.max(pad, Math.min(e.clientY, window.innerHeight - menuH - pad));
    setMenu({ x, y });
  };

  return (
    <div
      className={styles.tokenTile}
      draggable
      onDragStart={(e) => {
        if (menuBtnRef.current?.contains(e.target as Node)) {
          e.preventDefault();
          return;
        }
        e.dataTransfer.setData(TOKEN_DND_MIME, token.id);
        e.dataTransfer.effectAllowed = 'copy';
      }}
      title="Перетащите на карту"
    >
      <div className={styles.tokenThumb}>
        {url ? <img src={url} alt="" draggable={false} /> : null}
      </div>
      <div className={styles.tokenTileMeta}>
        <div className={styles.tokenTileName}>{token.name}</div>
        <button
          ref={menuBtnRef}
          type="button"
          className={styles.tokenTileMore}
          aria-label="Действия"
          aria-haspopup="menu"
          aria-expanded={menu !== null}
          title="Действия"
          onClick={openMenu}
          onPointerDown={(e) => e.stopPropagation()}
        >
          ⋮
        </button>
      </div>
      {menu
        ? createPortal(
            <div
              ref={menuRef}
              role="menu"
              className={styles.tokenCtxMenu}
              style={{ left: menu.x, top: menu.y }}
              onPointerDown={(e) => e.stopPropagation()}
            >
              <button
                type="button"
                role="menuitem"
                className={styles.tokenCtxItem}
                onClick={() => {
                  setMenu(null);
                  onEdit();
                }}
              >
                Изменить
              </button>
              <button
                type="button"
                role="menuitem"
                className={styles.tokenCtxItemDanger}
                onClick={() => {
                  setMenu(null);
                  onDelete();
                }}
              >
                Удалить
              </button>
            </div>,
            document.body,
          )
        : null}
    </div>
  );
}

export { TOKEN_DND_MIME };
