import React, { useEffect, useCallback, useRef } from 'react';
import { useEditor } from '@craftjs/core';
import { findDeletableTarget } from '../../utils/craft-helpers';
import { useSitesmithModal } from '../../state/SitesmithContext';
import { buildSitesmithTarget } from '../../utils/sitesmith-target';

interface ContextMenuProps {
  visible: boolean;
  x: number;
  y: number;
  nodeId: string | null;
  onClose: () => void;
}

interface MenuItem {
  label: string;
  shortcut?: string;
  action: () => void;
  danger?: boolean;
  disabled?: boolean;
  dividerAfter?: boolean;
}

export const ContextMenu: React.FC<ContextMenuProps> = ({
  visible,
  x,
  y,
  nodeId,
  onClose,
}) => {
  const { actions, query } = useEditor();
  const { open: openSitesmith } = useSitesmithModal();
  const menuRef = useRef<HTMLDivElement>(null);
  const clipboardRef = useRef<string | null>(null);

  // Close on click outside
  useEffect(() => {
    if (!visible) return;
    const handleClick = (e: MouseEvent) => {
      if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
        onClose();
      }
    };
    const handleEsc = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
    };
    document.addEventListener('mousedown', handleClick);
    document.addEventListener('keydown', handleEsc);
    return () => {
      document.removeEventListener('mousedown', handleClick);
      document.removeEventListener('keydown', handleEsc);
    };
  }, [visible, onClose]);

  const getParentId = useCallback((): string | null => {
    if (!nodeId) return null;
    try {
      const node = query.node(nodeId).get();
      return node?.data?.parent || null;
    } catch {
      return null;
    }
  }, [nodeId, query]);

  const duplicate = useCallback(() => {
    if (!nodeId || nodeId === 'ROOT') return;
    try {
      const tree = query.node(nodeId).toSerializedNode();
      const parentId = getParentId();
      if (!parentId) return;

      // Get the full subtree
      const freshTree = query.node(nodeId).toNodeTree();
      const clonedTree = query.parseSerializedNode(freshTree.nodes[freshTree.rootNodeId].data).toNode();

      actions.addNodeTree(freshTree, parentId);
    } catch (e) {
      console.error('Duplicate failed:', e);
    }
    onClose();
  }, [nodeId, actions, query, getParentId, onClose]);

  const copyNode = useCallback(() => {
    if (!nodeId || nodeId === 'ROOT') return;
    try {
      clipboardRef.current = nodeId;
    } catch (e) {
      console.error('Copy failed:', e);
    }
    onClose();
  }, [nodeId, onClose]);

  const pasteNode = useCallback(() => {
    const sourceId = clipboardRef.current;
    if (!sourceId) return;
    try {
      const targetParent = nodeId || 'ROOT';
      const tree = query.node(sourceId).toNodeTree();
      actions.addNodeTree(tree, targetParent);
    } catch (e) {
      console.error('Paste failed:', e);
    }
    onClose();
  }, [nodeId, actions, query, onClose]);

  const moveUp = useCallback(() => {
    if (!nodeId || nodeId === 'ROOT') return;
    try {
      const parentId = getParentId();
      if (!parentId) return;
      const parent = query.node(parentId).get();
      const children = parent.data.nodes || [];
      const idx = children.indexOf(nodeId);
      if (idx > 0) {
        actions.move(nodeId, parentId, idx - 1);
      }
    } catch (e) {
      console.error('Move up failed:', e);
    }
    onClose();
  }, [nodeId, actions, query, getParentId, onClose]);

  const moveDown = useCallback(() => {
    if (!nodeId || nodeId === 'ROOT') return;
    try {
      const parentId = getParentId();
      if (!parentId) return;
      const parent = query.node(parentId).get();
      const children = parent.data.nodes || [];
      const idx = children.indexOf(nodeId);
      if (idx < children.length - 1) {
        actions.move(nodeId, parentId, idx + 2);
      }
    } catch (e) {
      console.error('Move down failed:', e);
    }
    onClose();
  }, [nodeId, actions, query, getParentId, onClose]);

  const selectParent = useCallback(() => {
    if (!nodeId || nodeId === 'ROOT') return;
    const parentId = getParentId();
    if (parentId) {
      actions.selectNode(parentId);
    }
    onClose();
  }, [nodeId, actions, getParentId, onClose]);

  const askSitesmith = useCallback(() => {
    if (!nodeId || nodeId === 'ROOT') return;
    try {
      const target = buildSitesmithTarget(query, nodeId);
      if (target) openSitesmith(target);
    } catch (e) {
      console.error('Ask Sitesmith failed:', e);
    }
    onClose();
  }, [nodeId, query, openSitesmith, onClose]);

  const deleteNode = useCallback(() => {
    const target = findDeletableTarget(query, nodeId);
    if (!target) {
      onClose();
      return;
    }
    try {
      actions.delete(target);
    } catch (e) {
      console.error('Delete failed:', e);
    }
    onClose();
  }, [nodeId, actions, query, onClose]);

  if (!visible) return null;

  const isRoot = nodeId === 'ROOT' || !nodeId;

  const items: MenuItem[] = [
    {
      label: '✨ Ask Sitesmith',
      action: askSitesmith,
      disabled: isRoot,
      dividerAfter: true,
    },
    {
      label: 'Duplicate',
      shortcut: 'Ctrl+D',
      action: duplicate,
      disabled: isRoot,
    },
    {
      label: 'Copy',
      shortcut: 'Ctrl+C',
      action: copyNode,
      disabled: isRoot,
    },
    {
      label: 'Paste',
      shortcut: 'Ctrl+V',
      action: pasteNode,
      disabled: !clipboardRef.current,
      dividerAfter: true,
    },
    {
      label: 'Move Up',
      action: moveUp,
      disabled: isRoot,
    },
    {
      label: 'Move Down',
      action: moveDown,
      disabled: isRoot,
    },
    {
      label: 'Select Parent',
      action: selectParent,
      disabled: isRoot,
      dividerAfter: true,
    },
    {
      label: 'Delete',
      shortcut: 'Del',
      action: deleteNode,
      danger: true,
      disabled: isRoot,
    },
  ];

  // Adjust position to stay within viewport
  const adjustedX = Math.min(x, window.innerWidth - 200);
  const adjustedY = Math.min(y, window.innerHeight - items.length * 34 - 10);

  return (
    <div
      ref={menuRef}
      style={{
        position: 'fixed',
        top: adjustedY,
        left: adjustedX,
        zIndex: 10000,
        minWidth: 180,
        background: 'var(--color-bg-elevated)',
        border: '1px solid var(--color-border)',
        borderRadius: 'var(--radius-md)',
        boxShadow: '0 8px 24px rgba(0,0,0,0.5)',
        padding: '4px 0',
        overflow: 'hidden',
      }}
    >
      {items.map((item, i) => (
        <React.Fragment key={item.label}>
          <button
            onClick={item.disabled ? undefined : item.action}
            disabled={item.disabled}
            style={{
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'space-between',
              width: '100%',
              padding: '7px 12px',
              fontSize: 12,
              color: item.disabled
                ? 'var(--color-text-dim)'
                : item.danger
                  ? 'var(--color-danger)'
                  : 'var(--color-text)',
              background: 'transparent',
              border: 'none',
              cursor: item.disabled ? 'default' : 'pointer',
              textAlign: 'left',
              transition: 'background var(--transition-fast)',
            }}
            onMouseEnter={(e) => {
              if (!item.disabled) {
                (e.target as HTMLElement).style.background = 'var(--color-bg-hover)';
              }
            }}
            onMouseLeave={(e) => {
              (e.target as HTMLElement).style.background = 'transparent';
            }}
          >
            <span>{item.label}</span>
            {item.shortcut && (
              <span
                style={{
                  fontSize: 10,
                  color: 'var(--color-text-dim)',
                  marginLeft: 16,
                }}
              >
                {item.shortcut}
              </span>
            )}
          </button>
          {item.dividerAfter && (
            <div
              style={{
                height: 1,
                background: 'var(--color-border)',
                margin: '4px 0',
              }}
            />
          )}
        </React.Fragment>
      ))}
    </div>
  );
};
