/**
 * FileActionContextMenu — Floating Right-Click-Menu für FolderTree.
 *
 * Wird vom FolderTree gemountet wenn `onContextMenu` auf einer Zeile feuert.
 * Schließt sich bei Backdrop-Klick, ESC oder nach Aktion-Dispatch.
 */

import React, { useEffect, useRef } from 'react';
import {
  type FileAction,
  type FileActionContext,
  type FileActionTarget,
  resolveActionLabel,
} from './types';
import { runAction } from './registry';
import styles from './FileActionContextMenu.module.css';

interface Props {
  /** Sichtbar/positioniert. ``null`` → nicht gemountet. */
  anchor: { x: number; y: number } | null;
  actions: FileAction[];
  target: FileActionTarget;
  ctx: FileActionContext;
  /** Wird aufgerufen sobald das Menü schließen soll (Backdrop, ESC, nach Action). */
  onClose: () => void;
  /** Optional: Header-Label (z. B. Dateiname). */
  title?: string;
  /** Optionaler Confirm-Provider (z. B. browser native ``window.confirm``). */
  confirm?: (title: string, body: string) => boolean | Promise<boolean>;
}

export const FileActionContextMenu: React.FC<Props> = ({
  anchor,
  actions,
  target,
  ctx,
  onClose,
  title,
  confirm,
}) => {
  const menuRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!anchor) return;
    const _onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
    };
    window.addEventListener('keydown', _onKey);
    return () => window.removeEventListener('keydown', _onKey);
  }, [anchor, onClose]);

  useEffect(() => {
    if (!anchor || !menuRef.current) return;
    menuRef.current.focus();
  }, [anchor]);

  if (!anchor) return null;

  const adjusted = _adjustToViewport(anchor, menuRef.current);

  const _handleClick = async (action: FileAction) => {
    onClose();
    await runAction(action, target, ctx, confirm);
  };

  return (
    <>
      <div
        className={styles.backdrop}
        onClick={onClose}
        onContextMenu={(e) => {
          e.preventDefault();
          onClose();
        }}
      />
      <div
        ref={menuRef}
        className={styles.menu}
        role="menu"
        tabIndex={-1}
        style={{ left: adjusted.x, top: adjusted.y }}
      >
        {title && <div className={styles.header}>{title}</div>}
        {actions.length === 0 ? (
          <div className={styles.empty}>—</div>
        ) : (
          actions.map((a, idx) => {
            const Icon = a.icon;
            const isDangerCls = a.danger ? `${styles.item} ${styles.danger}` : styles.item;
            return (
              <React.Fragment key={a.id}>
                {idx > 0 && a.danger && actions[idx - 1] && !actions[idx - 1].danger && (
                  <div className={styles.divider} />
                )}
                <button
                  type="button"
                  role="menuitem"
                  className={isDangerCls}
                  onClick={() => _handleClick(a)}
                  style={a.iconColor ? { color: a.iconColor } : undefined}
                >
                  <span className={styles.icon}>
                    <Icon size={13} />
                  </span>
                  <span className={styles.label}>{resolveActionLabel(a, target)}</span>
                  {a.shortcut && <span className={styles.shortcut}>{_formatShortcut(a.shortcut)}</span>}
                </button>
              </React.Fragment>
            );
          })
        )}
      </div>
    </>
  );
};

function _adjustToViewport(
  anchor: { x: number; y: number },
  menu: HTMLDivElement | null,
): { x: number; y: number } {
  if (!menu) return anchor;
  const rect = menu.getBoundingClientRect();
  const vw = window.innerWidth;
  const vh = window.innerHeight;
  const margin = 4;
  let x = anchor.x;
  let y = anchor.y;
  if (x + rect.width + margin > vw) x = Math.max(margin, vw - rect.width - margin);
  if (y + rect.height + margin > vh) y = Math.max(margin, vh - rect.height - margin);
  return { x, y };
}

function _formatShortcut(s: string): string {
  const isMac = typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.platform);
  return s
    .split('+')
    .map((part) => {
      const k = part.trim().toLowerCase();
      if (k === 'mod') return isMac ? '\u2318' : 'Ctrl';
      if (k === 'shift') return isMac ? '\u21E7' : 'Shift';
      if (k === 'alt') return isMac ? '\u2325' : 'Alt';
      if (k === 'ctrl') return 'Ctrl';
      return k.length === 1 ? k.toUpperCase() : part;
    })
    .join(isMac ? '' : '+');
}
