'use client';

/**
 * Layer Context Menu Component
 *
 * Right-click context menu for layers with clipboard operations
 * Works in both LayersTree sidebar and canvas
 */

import React, { useMemo, useState } from 'react';
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuLabel,
  ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger,
  ContextMenuTrigger,
} from '@/components/ui/context-menu';
import { useCanvasPortalContainer, useCanvasZoom } from '@/lib/canvas-portal-context';
import { useEditorStore } from '@/stores/useEditorStore';
import { usePagesStore } from '@/stores/usePagesStore';
import { useClipboardStore } from '@/stores/useClipboardStore';
import { useComponentsStore } from '@/stores/useComponentsStore';
import { canHaveChildren, findLayerById, getClassesString, getLayerIcon, getLayerName, regenerateInteractionIds, canCopyLayer, canDeleteLayer, regenerateIdsWithInteractionRemapping, removeLayerById, findParentAndIndex, insertLayerAfter, updateLayerProps, canConvertToCollection, isExcludedFromCollection, getCollectionVariable, resetBindingsOnCollectionSourceChange } from '@/lib/layer-utils';
import { cloneDeep } from 'lodash';
import { toast } from 'sonner';
import { Icon } from '@/components/ui/icon';
import { detachSpecificLayerFromComponent, checkCircularReference } from '@/lib/component-utils';
import type { UseLiveLayerUpdatesReturn } from '@/hooks/use-live-layer-updates';
import type { UseLiveComponentUpdatesReturn } from '@/hooks/use-live-component-updates';
import type { Layer } from '@/types';
import CreateComponentDialog from './CreateComponentDialog';
import SaveLayoutDialog from './SaveLayoutDialog';

interface LayerContextMenuProps {
  layerId: string;
  pageId: string;
  children: React.ReactNode;
  isLocked?: boolean;
  onLayerSelect?: (layerId: string) => void;
  selectedLayerId?: string | null;
  liveLayerUpdates?: UseLiveLayerUpdatesReturn | null;
  liveComponentUpdates?: UseLiveComponentUpdatesReturn | null;
  /** When set, we're editing a component; resolve layer from component draft so "Detach" works for nested instances */
  editingComponentId?: string | null;
}

let pendingCloseRaf = 0;
let activeMenuDocument: Document | null = null;
let selectionFromMenu = false;

function dismissActiveContextMenu() {
  if (activeMenuDocument) {
    activeMenuDocument.dispatchEvent(
      new PointerEvent('pointerdown', { bubbles: true })
    );
    activeMenuDocument = null;
  }
}

// Close any open context menu when a different layer is selected (e.g. via sidebar or canvas click)
useEditorStore.subscribe((state, prevState) => {
  if (state.selectedLayerId !== prevState.selectedLayerId) {
    if (selectionFromMenu) {
      selectionFromMenu = false;
      return;
    }
    dismissActiveContextMenu();
  }
});

export default function LayerContextMenu({
  layerId,
  pageId,
  children,
  isLocked = false,
  onLayerSelect,
  selectedLayerId,
  liveLayerUpdates,
  liveComponentUpdates,
  editingComponentId = null,
}: LayerContextMenuProps) {
  const [isComponentDialogOpen, setIsComponentDialogOpen] = useState(false);
  const [isLayoutDialogOpen, setIsLayoutDialogOpen] = useState(false);
  const [layerName, setLayerName] = useState('');
  const canvasPortalContainer = useCanvasPortalContainer();
  const canvasZoom = useCanvasZoom();

  const copyLayer = usePagesStore((state) => state.copyLayer);
  const deleteLayer = usePagesStore((state) => state.deleteLayer);
  const duplicateLayer = usePagesStore((state) => state.duplicateLayer);
  const pasteAfter = usePagesStore((state) => state.pasteAfter);
  const pasteInside = usePagesStore((state) => state.pasteInside);
  const updateLayer = usePagesStore((state) => state.updateLayer);
  const setDraftLayers = usePagesStore((state) => state.setDraftLayers);
  const draftsByPageId = usePagesStore((state) => state.draftsByPageId);
  const createComponentFromLayer = usePagesStore((state) => state.createComponentFromLayer);

  const loadComponents = useComponentsStore((state) => state.loadComponents);
  const getComponentById = useComponentsStore((state) => state.getComponentById);
  const components = useComponentsStore((state) => state.components);
  const componentDrafts = useComponentsStore((state) => state.componentDrafts);
  const updateComponentDraft = useComponentsStore((state) => state.updateComponentDraft);
  const createComponentFromComponentLayer = useComponentsStore((state) => state.createComponentFromLayer);

  const clipboardLayer = useClipboardStore((state) => state.clipboardLayer);
  const clipboardMode = useClipboardStore((state) => state.clipboardMode);
  const copyToClipboard = useClipboardStore((state) => state.copyLayer);
  const cutToClipboard = useClipboardStore((state) => state.cutLayer);
  const copyStyleToClipboard = useClipboardStore((state) => state.copyStyle);
  const pasteStyleFromClipboard = useClipboardStore((state) => state.pasteStyle);
  const copiedStyle = useClipboardStore((state) => state.copiedStyle);
  const copyInteractionsToClipboard = useClipboardStore((state) => state.copyInteractions);
  const pasteInteractionsFromClipboard = useClipboardStore((state) => state.pasteInteractions);
  const copiedInteractions = useClipboardStore((state) => state.copiedInteractions);

  const hasClipboard = clipboardLayer !== null;
  const hasStyleClipboard = copiedStyle !== null;
  const hasInteractionsClipboard = copiedInteractions !== null;

  // Resolve layers: component draft when editing a component, else page draft
  const isComponentContext = !!editingComponentId;
  const layers = useMemo(
    () =>
      isComponentContext
        ? (componentDrafts[editingComponentId!] || [])
        : (draftsByPageId[pageId]?.layers || []),
    [isComponentContext, editingComponentId, componentDrafts, draftsByPageId, pageId]
  );
  const layer = findLayerById(layers, layerId);

  const isComponentInstance = !!(layer && layer.componentId);
  const componentName = isComponentInstance && layer?.componentId
    ? getComponentById(layer.componentId)?.name
    : null;

  // Check if the current layer can have children
  const canPasteInside = useMemo(() => {
    const targetLayer = findLayerById(layers, layerId);
    if (!targetLayer) return false;
    return canHaveChildren(targetLayer);
  }, [layers, layerId]);

  const isBody = layerId === 'body';

  // Check layer restrictions
  const canCopy = useMemo(() => {
    if (!layer) return false;
    return canCopyLayer(layer);
  }, [layer]);

  const canDelete = useMemo(() => {
    if (!layer) return false;
    return canDeleteLayer(layer);
  }, [layer]);

  /** Update component draft layers and broadcast to collaborators */
  const updateComponentAndBroadcast = (newLayers: Layer[]) => {
    if (!editingComponentId) return;
    updateComponentDraft(editingComponentId, newLayers);
    if (liveComponentUpdates) {
      liveComponentUpdates.broadcastComponentLayersUpdate(editingComponentId, newLayers);
    }
  };

  /** Get current component layers for the editing context */
  const getComponentLayers = () =>
    editingComponentId ? (componentDrafts[editingComponentId] || []) : [];

  const handleCopy = () => {
    if (!canCopy) return;

    // In component context, copy from component drafts
    if (isComponentContext && editingComponentId) {
      const layerToCopy = findLayerById(getComponentLayers(), layerId);
      if (layerToCopy) {
        copyToClipboard(cloneDeep(layerToCopy), pageId);
      }
    } else {
      const layer = copyLayer(pageId, layerId);
      if (layer) {
        copyToClipboard(layer, pageId);
      }
    }
  };

  const handleCut = () => {
    if (isLocked || !canCopy || !canDelete) return;

    // In component context, cut from component drafts
    if (isComponentContext && editingComponentId) {
      const layerToCopy = findLayerById(getComponentLayers(), layerId);
      if (layerToCopy) {
        cutToClipboard(cloneDeep(layerToCopy), pageId);
        updateComponentAndBroadcast(removeLayerById(getComponentLayers(), layerId));

        if (onLayerSelect) {
          onLayerSelect(null as any);
        }
      }
    } else {
      const layer = copyLayer(pageId, layerId);
      if (layer) {
        cutToClipboard(layer, pageId);
        deleteLayer(pageId, layerId);

        // Broadcast delete to other collaborators
        if (liveLayerUpdates) {
          liveLayerUpdates.broadcastLayerDelete(pageId, layerId);
        }

        // Clear selection after cut to match keyboard shortcut behavior
        if (onLayerSelect) {
          onLayerSelect(null as any);
        }
      }
    }
  };

  const handlePasteAfter = () => {
    if (!clipboardLayer) return;

    if (isComponentContext && editingComponentId) {
      const circularError = checkCircularReference(editingComponentId, clipboardLayer, components);
      if (circularError) {
        toast.error('Infinite component loop detected', { description: circularError });
        return;
      }

      const componentLayers = getComponentLayers();
      const newLayer = regenerateIdsWithInteractionRemapping(cloneDeep(clipboardLayer));
      const result = findParentAndIndex(componentLayers, layerId);
      if (!result) return;

      updateComponentAndBroadcast(insertLayerAfter(componentLayers, result.parent, result.index, newLayer));
    } else {
      const pastedLayer = pasteAfter(pageId, layerId, clipboardLayer);
      if (liveLayerUpdates && pastedLayer) {
        liveLayerUpdates.broadcastLayerAdd(pageId, null, 'paste', pastedLayer);
      }
    }
  };

  const handlePasteInside = () => {
    if (!clipboardLayer || !canPasteInside) return;

    if (isComponentContext && editingComponentId) {
      const circularError = checkCircularReference(editingComponentId, clipboardLayer, components);
      if (circularError) {
        toast.error('Infinite component loop detected', { description: circularError });
        return;
      }

      const componentLayers = getComponentLayers();
      const newLayer = regenerateIdsWithInteractionRemapping(cloneDeep(clipboardLayer));
      updateComponentAndBroadcast(
        updateLayerProps(componentLayers, layerId, { children: [...(findLayerById(componentLayers, layerId)?.children || []), newLayer] })
      );
    } else {
      const pastedLayer = pasteInside(pageId, layerId, clipboardLayer);
      if (liveLayerUpdates && pastedLayer) {
        liveLayerUpdates.broadcastLayerAdd(pageId, layerId, 'paste', pastedLayer);
      }
    }
  };

  const handleDuplicate = () => {
    if (!canCopy) return;

    if (isComponentContext && editingComponentId) {
      const componentLayers = getComponentLayers();
      const layerToCopy = findLayerById(componentLayers, layerId);
      if (!layerToCopy) return;

      const newLayer = regenerateIdsWithInteractionRemapping(cloneDeep(layerToCopy));
      const result = findParentAndIndex(componentLayers, layerId);
      if (!result) return;

      updateComponentAndBroadcast(insertLayerAfter(componentLayers, result.parent, result.index, newLayer));
    } else {
      const duplicatedLayer = duplicateLayer(pageId, layerId);
      // Broadcast the duplicated layer
      if (liveLayerUpdates && duplicatedLayer) {
        liveLayerUpdates.broadcastLayerAdd(pageId, null, 'duplicate', duplicatedLayer);
      }
    }
  };

  const handleDelete = () => {
    if (isLocked || !canDelete) return;

    if (isComponentContext && editingComponentId) {
      updateComponentAndBroadcast(removeLayerById(getComponentLayers(), layerId));

      if (onLayerSelect) {
        onLayerSelect(null as any);
      }
    } else {
      deleteLayer(pageId, layerId);

      // Broadcast delete to other collaborators
      if (liveLayerUpdates) {
        liveLayerUpdates.broadcastLayerDelete(pageId, layerId);
      }

      // Clear selection after delete to match keyboard shortcut behavior
      if (onLayerSelect) {
        onLayerSelect(null as any);
      }
    }
  };

  const handleRename = () => {
    if (!layer) return;
    useEditorStore.getState().setRenamingLayerId(layerId);
  };

  const handleCopyStyle = () => {
    if (!layer) return;

    const classes = getClassesString(layer);
    copyStyleToClipboard(classes, layer.design, layer.styleId, layer.styleOverrides);
  };

  const handlePasteStyle = () => {
    const style = pasteStyleFromClipboard();
    if (!style) return;

    const styleProps = {
      classes: style.classes,
      design: style.design,
      styleId: style.styleId,
      styleOverrides: style.styleOverrides,
    };

    if (isComponentContext && editingComponentId) {
      updateComponentAndBroadcast(updateLayerProps(getComponentLayers(), layerId, styleProps));
    } else {
      updateLayer(pageId, layerId, styleProps);
    }
  };

  const handleCopyInteractions = () => {
    if (!layer || !layer.interactions || layer.interactions.length === 0) return;

    copyInteractionsToClipboard(layer.interactions, layerId);
  };

  const handlePasteInteractions = () => {
    const copiedData = pasteInteractionsFromClipboard();
    if (!copiedData) return;

    const { interactions, sourceLayerId } = copiedData;

    const layerIdMap = new Map<string, string>();
    layerIdMap.set(sourceLayerId, layerId);
    const updatedInteractions = regenerateInteractionIds(interactions, layerIdMap);

    if (isComponentContext && editingComponentId) {
      updateComponentAndBroadcast(updateLayerProps(getComponentLayers(), layerId, { interactions: updatedInteractions }));
    } else {
      updateLayer(pageId, layerId, { interactions: updatedInteractions });
    }
  };

  const handleCreateComponent = () => {
    // Use the already-resolved layer (works in both page and component context)
    if (!layer) return;

    const defaultName = layer.customName || layer.name || 'Component';
    setLayerName(defaultName);
    setIsComponentDialogOpen(true);
  };

  const handleConfirmCreateComponent = async (componentName: string) => {
    // Use appropriate creation function based on context
    const componentId = isComponentContext && editingComponentId
      ? await createComponentFromComponentLayer(editingComponentId, layerId, componentName)
      : await createComponentFromLayer(pageId, layerId, componentName);

    if (!componentId) return;

    // Broadcast to collaborators
    if (liveComponentUpdates) {
      const component = getComponentById(componentId);
      if (component) {
        liveComponentUpdates.broadcastComponentCreate(component);
      }
    }
  };

  const handleEditMasterComponent = async () => {
    if (!layer?.componentId) return;

    const { setEditingComponentId, setSelectedLayerId, pushComponentNavigation, editingComponentId } = useEditorStore.getState();
    const { loadComponentDraft, getComponentById } = useComponentsStore.getState();
    const { pages } = usePagesStore.getState();

    // Capture the current layer ID BEFORE clearing selection
    // This is the layer we'll return to when exiting component edit mode
    const componentInstanceLayerId = layer.id;

    // Push current context to navigation stack before entering component edit mode
    if (editingComponentId) {
      // We're currently editing a component, push it to stack
      const currentComponent = getComponentById(editingComponentId);
      if (currentComponent) {
        pushComponentNavigation({
          type: 'component',
          id: editingComponentId,
          name: currentComponent.name,
          layerId: layer.id,
        });
      }
    } else if (pageId) {
      // We're on a page, push it to stack
      const currentPage = pages.find((p) => p.id === pageId);
      if (currentPage) {
        pushComponentNavigation({
          type: 'page',
          id: pageId,
          name: currentPage.name,
          layerId: componentInstanceLayerId,
        });
      }
    }

    // Clear selection FIRST to release lock on current page's channel
    // before switching to component's channel
    setSelectedLayerId(null);

    // Enter edit mode (changes lock channel to component)
    // Pass the component instance layer ID so we can restore it when exiting
    setEditingComponentId(layer.componentId, pageId, componentInstanceLayerId);

    // Load component into draft (async to ensure proper cache sync)
    await loadComponentDraft(layer.componentId);

    // Select root layer only if user hasn't already selected a valid component layer during the await
    const component = getComponentById(layer.componentId);
    if (component && component.layers && component.layers.length > 0) {
      const currentSelection = useEditorStore.getState().selectedLayerId;
      const hasValidSelection = currentSelection && findLayerById(component.layers, currentSelection);
      if (!hasValidSelection) {
        setSelectedLayerId(component.layers[0].id);
      }
    }
  };

  const handleDetachFromComponent = () => {
    if (!layer || !layer.componentId) return;

    const component = getComponentById(layer.componentId);

    // Use the shared utility function for detaching
    const newLayers = detachSpecificLayerFromComponent(layers, layerId, component || undefined);

    if (isComponentContext && editingComponentId) {
      updateComponentDraft(editingComponentId, newLayers);
    } else {
      setDraftLayers(pageId, newLayers);
    }

    if (onLayerSelect) {
      onLayerSelect(null as any);
    }
  };

  const handleShowJSON = () => {
    if (!layer) return;
    console.log('Layer:', layer);
  };

  const handleSaveAsLayout = () => {
    if (!layer) return;

    // Set default name from layer
    const defaultName = layer.customName || layer.name || 'Custom Layout';
    setLayerName(defaultName);

    // Open dialog
    setIsLayoutDialogOpen(true);
  };

  const handleConfirmSaveLayout = async (layoutName: string, category: string, imageFile: File | null) => {
    if (!layer) return;

    try {
      // Collect all layer IDs that are referenced by animations (tween.layer_id)
      // These IDs must be preserved so animations work when layout is loaded
      const collectReferencedLayerIds = (l: Layer): Set<string> => {
        const ids = new Set<string>();

        // Check interactions on this layer
        if (l.interactions) {
          l.interactions.forEach(interaction => {
            interaction.tweens?.forEach(tween => {
              if (tween.layer_id) {
                ids.add(tween.layer_id);
              }
            });
          });
        }

        // Recursively check children
        if (l.children) {
          l.children.forEach(child => {
            collectReferencedLayerIds(child).forEach(id => ids.add(id));
          });
        }

        return ids;
      };

      const referencedLayerIds = collectReferencedLayerIds(layer);

      // Strip IDs to convert Layer to LayerTemplate
      // But preserve IDs that are referenced by animations
      const stripIds = (l: Layer): any => {
        const { id, ...rest } = l;
        const result: any = { ...rest };

        // Preserve ID if it's referenced by an animation
        if (referencedLayerIds.has(id)) {
          result.id = id;
        }

        if (result.children && Array.isArray(result.children)) {
          result.children = result.children.map((child: Layer) => stripIds(child));
        }

        return result;
      };

      const template = stripIds(layer);

      // Generate layout key from name
      const layoutKey = layoutName.toLowerCase().replace(/\s+/g, '-');

      // Use FormData to send file + data
      const formData = new FormData();
      formData.append('layoutKey', layoutKey);
      formData.append('layoutName', layoutName);
      formData.append('category', category);
      formData.append('template', JSON.stringify(template));
      formData.append('pageId', pageId);
      formData.append('layerId', layerId);

      if (imageFile) {
        formData.append('image', imageFile);
      }

      // Call API to save layout
      const response = await fetch('/ycode/api/layouts', {
        method: 'POST',
        body: formData,
      });

      const result = await response.json();

      if (!response.ok) {
        throw new Error(result.error || 'Failed to save layout');
      }
    } catch (error) {
      console.error('Failed to save layout:', error);
      throw error;
    }
  };

  const handleConvertToCollection = () => {
    if (!layer || !canConvertToCollection(layer)) return;

    const updatedVariables = {
      ...layer.variables,
      collection: { id: '' },
    };

    if (isComponentContext && editingComponentId) {
      updateComponentAndBroadcast(
        updateLayerProps(getComponentLayers(), layerId, { variables: updatedVariables })
      );
    } else {
      updateLayer(pageId, layerId, { variables: updatedVariables });
      if (liveLayerUpdates) {
        liveLayerUpdates.broadcastLayerUpdate(layerId, { variables: updatedVariables });
      }
    }
  };

  const handleDetachCollection = () => {
    if (!layer || !getCollectionVariable(layer)) return;

    const { collection, ...restVariables } = layer.variables || {};
    const updatedVariables = { ...restVariables, collection: undefined };

    if (isComponentContext && editingComponentId) {
      const componentLayers = getComponentLayers();
      let newLayers = updateLayerProps(componentLayers, layerId, { variables: updatedVariables });
      newLayers = resetBindingsOnCollectionSourceChange(newLayers, layerId);
      updateComponentAndBroadcast(newLayers);
    } else {
      updateLayer(pageId, layerId, { variables: updatedVariables });

      setTimeout(() => {
        const currentLayers = usePagesStore.getState().draftsByPageId[pageId]?.layers;
        if (!currentLayers) return;

        const cleanedLayers = resetBindingsOnCollectionSourceChange(currentLayers, layerId);
        if (cleanedLayers !== currentLayers) {
          setDraftLayers(pageId, cleanedLayers);
        }
      }, 0);

      if (liveLayerUpdates) {
        liveLayerUpdates.broadcastLayerUpdate(layerId, { variables: updatedVariables });
      }
    }
  };

  const isCollection = !!(layer && getCollectionVariable(layer));
  const canConvert = !!(layer && canConvertToCollection(layer));
  const showConvertOption = !!(layer && !isCollection && canHaveChildren(layer) && !layer.componentId);
  const isConvertDisabled = isLocked || isComponentInstance || !!(layer && isExcludedFromCollection(layer));

  const handleOpenChange = (open: boolean) => {
    if (open) {
      dismissActiveContextMenu();
      activeMenuDocument = canvasPortalContainer?.ownerDocument ?? document;
    }

    if (open && onLayerSelect && layer && selectedLayerId !== layerId) {
      selectionFromMenu = true;
      onLayerSelect(layerId);
    }
    // Hide the parent-document selection overlay while the canvas context menu is open,
    // and suppress stale clicks that fire on the canvas when the menu dismisses
    if (canvasPortalContainer) {
      if (open) {
        cancelAnimationFrame(pendingCloseRaf);
        useEditorStore.getState().setCanvasContextMenuOpen(true);
      } else {
        pendingCloseRaf = requestAnimationFrame(() => {
          useEditorStore.getState().setCanvasContextMenuOpen(false);
        });
      }
    }
  };

  // Check if we're on localhost
  const isLocalhost = typeof window !== 'undefined' && window.location.hostname === 'localhost';

  return (
    <ContextMenu onOpenChange={handleOpenChange}>
      <ContextMenuTrigger
        asChild
        onContextMenu={(e) => e.stopPropagation()}
      >
        {children}
      </ContextMenuTrigger>
      <ContextMenuContent
        className="w-46"
        container={canvasPortalContainer}
        style={canvasPortalContainer ? { zoom: 100 / canvasZoom } : undefined}
      >
        {canvasPortalContainer && layer && (
          <>
            <ContextMenuLabel className="flex items-center gap-1.5 font-normal text-muted-foreground select-none">
              <Icon
                name={getLayerIcon(layer)}
                className="size-3"
              />
              <span className="truncate">{getLayerName(layer)}</span>
            </ContextMenuLabel>
            <ContextMenuSeparator />
          </>
        )}

        <ContextMenuItem onClick={handleCut} disabled={isLocked || !canCopy || !canDelete}>
          Cut
          <ContextMenuShortcut>⌘X</ContextMenuShortcut>
        </ContextMenuItem>

        <ContextMenuItem onClick={handleCopy} disabled={!canCopy}>
          Copy
          <ContextMenuShortcut>⌘C</ContextMenuShortcut>
        </ContextMenuItem>

        <ContextMenuSub>
          <ContextMenuSubTrigger>Paste</ContextMenuSubTrigger>
          <ContextMenuSubContent
            container={canvasPortalContainer}
            style={canvasPortalContainer ? { zoom: 100 / canvasZoom } : undefined}
          >
            <ContextMenuItem onClick={handlePasteAfter} disabled={!hasClipboard || isBody}>
              Paste after
              <ContextMenuShortcut>⌘V</ContextMenuShortcut>
            </ContextMenuItem>

            <ContextMenuItem onClick={handlePasteInside} disabled={!hasClipboard || !canPasteInside}>
              Paste inside
              <ContextMenuShortcut>⌘⇧V</ContextMenuShortcut>
            </ContextMenuItem>
          </ContextMenuSubContent>
        </ContextMenuSub>

        <ContextMenuItem onClick={handleDuplicate} disabled={!canCopy}>
          Duplicate
          <ContextMenuShortcut>⌘D</ContextMenuShortcut>
        </ContextMenuItem>

        <ContextMenuItem
          onClick={handleDelete}
          disabled={isLocked || !canDelete}
        >
          Delete
          <ContextMenuShortcut>⌫</ContextMenuShortcut>
        </ContextMenuItem>

        {!canvasPortalContainer && (
          <>
            <ContextMenuSeparator />

            <ContextMenuItem onClick={handleRename} disabled={isBody}>
              Rename
              <ContextMenuShortcut>F2</ContextMenuShortcut>
            </ContextMenuItem>
          </>
        )}

        {!isComponentInstance && (
          <>
            <ContextMenuSeparator />

            <ContextMenuItem onClick={handleCopyStyle}>
              Copy style
              <ContextMenuShortcut>⌥⌘C</ContextMenuShortcut>
            </ContextMenuItem>

            <ContextMenuItem onClick={handlePasteStyle} disabled={!hasStyleClipboard}>
              Paste style
              <ContextMenuShortcut>⌥⌘V</ContextMenuShortcut>
            </ContextMenuItem>

            <ContextMenuSeparator />

            <ContextMenuItem onClick={handleCopyInteractions} disabled={!layer?.interactions || layer.interactions.length === 0}>
              Copy interactions
              <ContextMenuShortcut><Icon name="zap" className="size-3" /></ContextMenuShortcut>
            </ContextMenuItem>

            <ContextMenuItem onClick={handlePasteInteractions} disabled={!hasInteractionsClipboard}>
              Paste interactions
              <ContextMenuShortcut><Icon name="zap" className="size-3" /></ContextMenuShortcut>
            </ContextMenuItem>
          </>
        )}

        {(showConvertOption || isCollection) && (
          <>
            <ContextMenuSeparator />

            {showConvertOption && (
              <ContextMenuItem onClick={handleConvertToCollection} disabled={isConvertDisabled}>
                Convert to collection
                <ContextMenuShortcut><Icon name="database" className="size-3" /></ContextMenuShortcut>
              </ContextMenuItem>
            )}

            {isCollection && (
              <ContextMenuItem onClick={handleDetachCollection} disabled={isLocked || isComponentInstance}>
                Detach collection
                <ContextMenuShortcut><Icon name="database" className="size-3" /></ContextMenuShortcut>
              </ContextMenuItem>
            )}
          </>
        )}

        <ContextMenuSeparator />

        {isComponentInstance ? (
          <>
            <ContextMenuItem onClick={handleEditMasterComponent}>
              Edit master component
              <ContextMenuShortcut><Icon name="edit" className="size-3" /></ContextMenuShortcut>
            </ContextMenuItem>

            <ContextMenuItem onClick={handleDetachFromComponent}>
              Detach component
              <ContextMenuShortcut><Icon name="detach" className="size-3" /></ContextMenuShortcut>
            </ContextMenuItem>
          </>
        ) : (
          <ContextMenuItem onClick={handleCreateComponent} disabled={isLocked}>
            Create component
            <ContextMenuShortcut><Icon name="component" className="size-3" /></ContextMenuShortcut>
          </ContextMenuItem>
        )}

        {/* Development only: Show JSON */}
        {process.env.NODE_ENV === 'development' && (
          <>
            <ContextMenuSeparator />

            <ContextMenuItem onClick={handleShowJSON}>
              Show JSON
              <ContextMenuShortcut><Icon name="code" className="size-3" /></ContextMenuShortcut>
            </ContextMenuItem>

            <ContextMenuItem onClick={handleSaveAsLayout}>
              Save as Layout
              <ContextMenuShortcut><Icon name="layout" className="size-3" /></ContextMenuShortcut>
            </ContextMenuItem>
          </>
        )}
      </ContextMenuContent>

      <CreateComponentDialog
        open={isComponentDialogOpen}
        onOpenChange={setIsComponentDialogOpen}
        onConfirm={handleConfirmCreateComponent}
        layerName={layerName}
      />

      <SaveLayoutDialog
        open={isLayoutDialogOpen}
        onOpenChange={setIsLayoutDialogOpen}
        onConfirm={handleConfirmSaveLayout}
        defaultName={layerName}
      />
    </ContextMenu>
  );
}
