/**
 * Toolbar - Main toolbar component for the workflow modeler
 * 
 * Provides actions for saving, editing, zooming, searching, and other
 * model manipulation operations.
 */

import React, { useCallback, useRef, useEffect, useMemo } from 'react';
import { FiSave, FiZoomIn, FiZoomOut, FiMaximize, FiMaximize2, FiMinimize2, FiSettings, FiLock, FiUnlock, FiX, FiLayout, FiMinus, FiCopy, FiClipboard, FiSearch, FiMessageSquare, FiZap, FiMap, FiHash, FiMoon, FiSun, FiTrash2, FiBookOpen, FiDownload } from 'react-icons/fi';
import type { ViewMode } from '../hooks/useViewMode';
import { useReactFlow } from 'reactflow';
import { Node, Edge, useStore, Component } from '../store/store';
import SearchBar, { SearchBarRef } from './SearchBar';
import StartFlowFilter from './StartFlowFilter';
import QuickAddEventButton from './QuickAddEventButton';
import ToolbarOverflowMenu, { OverflowItem } from './ToolbarOverflowMenu';
import { t } from '../utils/translation';
import { useSaveModel } from '../hooks/useSaveModel';
import { useToolbarHandlers, isAtMinZoom, isAtMaxZoom } from '../hooks/useToolbarHandlers';
import { useToolbarOverflow } from '../hooks/useToolbarOverflow';
import { getFitViewport } from '../utils/modelUtils';
import type { Settings, DrupalAjax, ModelerContext } from '../types/settings';

interface SearchResult {
  id: string;
  type: 'node' | 'edge';
  label: string;
  subtitle: string;
  data: Node | Edge;
}

interface ToolbarProps {
  onSave?: () => any;
  onSaveComplete?: () => void;
  onOpenMetadata: () => void;
  onToggleLock: () => void;
  onAutoLayout: () => void;
  onCopy: () => void;
  onPaste: () => void;
  onToggleSearch: () => void;
  onToggleAllAnnotations: () => void;
  onToggleMessages: () => void;
  onClearMessages: () => void;
  onToggleMinimap: () => void;
  onToggleEdgeOrders: () => void;
  isLocked: boolean;
  /** When true, all editing is disabled — hides paste, auto-layout, save, lock toggle, copy */
  isReadOnly?: boolean;
  isSearchVisible: boolean;
  isMinimapVisible: boolean;
  hasSelection?: boolean;
  canPaste?: boolean;
  nodes?: Node[];
  edges?: Edge[];
  allAnnotationsVisible?: boolean;
  edgeOrdersVisible?: boolean;
  hasMessages?: boolean;
  messagesVisible?: boolean;
  onSearchHighlight?: (result: SearchResult | null) => void;
  onSearchFocus?: (data: Node | Edge) => void;
  zoomLevel?: number;
  modelName?: string;
  hasUnsavedChanges?: boolean;
  onClose?: () => void;
  onMinimize?: () => void;
  settings?: Settings;
  drupal?: DrupalAjax;
  saveButtonRef?: React.RefObject<HTMLButtonElement | null>;
  /** Screen reader announcement callback */
  announce?: (text: string) => void;
  /** Available contexts from drupalSettings.modeler_api.contexts */
  contexts?: ModelerContext[];
  /** Currently selected context ID (null = none) */
  selectedContextId?: string | null;
  /** Callback when the user selects a context */
  onContextChange?: (contextId: string | null) => void;
  /** Callback when user adds a new event via quick-add */
  onAddEvent?: (component: Component) => void;
  /** Whether the event popup is open (controlled) */
  isEventPopupOpen?: boolean;
  /** Callback when event popup open state changes */
  onEventPopupOpenChange?: (isOpen: boolean) => void;
  /** Callback when user clicks the export button */
  onExport?: () => void;
  /** Whether the export button should be visible */
  canExport?: boolean;
  /** Current view mode: fullscreen or restored */
  viewMode?: ViewMode;
  /** Toggle between fullscreen and restored */
  onToggleViewMode?: () => void;
  /** Start dragging the window (for restored Drupal mode) */
  onStartDrag?: (e: React.MouseEvent) => void;
}

const Toolbar: React.FC<ToolbarProps> = ({
  onSave,
  onSaveComplete,
  onOpenMetadata,
  onToggleLock,
  onAutoLayout,
  onCopy,
  onPaste,
  onToggleSearch,
  onToggleAllAnnotations,
  onToggleMessages,
  onClearMessages,
  onToggleMinimap,
  onToggleEdgeOrders,
  isLocked,
  isReadOnly = false,
  isSearchVisible,
  isMinimapVisible,
  hasSelection = false,
  canPaste = false,
  nodes = [],
  edges = [],
  allAnnotationsVisible = false,
  edgeOrdersVisible = false,
  hasMessages = false,
  messagesVisible = false,
  onSearchHighlight,
  onSearchFocus,
  zoomLevel = 1,
  modelName = t('Untitled Model'),
  hasUnsavedChanges = false,
  onClose,
  onMinimize,
  settings = {},
  drupal,
  saveButtonRef,
  announce,
  contexts = [],
  selectedContextId = null,
  onContextChange,
  onAddEvent,
  isEventPopupOpen,
  onEventPopupOpenChange,
  onExport,
  canExport = false,
  viewMode = 'fullscreen',
  onToggleViewMode,
  onStartDrag,
}) => {
  const searchBarRef = useRef<SearchBarRef>(null);
  const toolbarRef = useRef<HTMLDivElement>(null);
  const toolbarRightRef = useRef<HTMLDivElement>(null);

  // Overflow detection for the right region (+ compact mode for whole toolbar)
  const { overflowedIds, showOverflowMenu, compactMode } = useToolbarOverflow(toolbarRightRef, toolbarRef);

  // Dark mode from store
  const darkMode = useStore(state => state.darkMode);
  const toggleDarkMode = useStore(state => state.toggleDarkMode);

  // Use extracted save model hook
  const { handleSave } = useSaveModel({
    onSave,
    onSaveComplete,
    settings,
    drupal,
    announce,
  });

  // Use extracted toolbar handlers hook
  const {
    handleToggleLock,
    handleAutoLayout,
    handleCopy,
    handlePaste,
    handleToggleSearch,
    handleClose,
    handleMinimize,
    handleZoomIn,
    handleZoomOut,
    handleFitView,
  } = useToolbarHandlers({
    onToggleLock,
    onAutoLayout,
    onCopy,
    onPaste,
    onToggleSearch,
    onClose,
    onMinimize,
  });

  // Direct ReactFlow accessors for overflow menu (no MouseEvent needed)
  const reactFlow = useReactFlow();
  const directZoomIn = useCallback(() => reactFlow.zoomIn(), [reactFlow]);
  const directZoomOut = useCallback(() => reactFlow.zoomOut(), [reactFlow]);
  const directFitView = useCallback(() => {
    const allNodes = reactFlow.getNodes();
    const visibleUnlockedNodes = allNodes.filter(
      (node: { data?: { locked?: boolean }; hidden?: boolean }) => !node.data?.locked && !node.hidden,
    );
    if (visibleUnlockedNodes.length > 0) {
      const viewportWidth = window.innerWidth * 0.6;
      const viewportHeight = window.innerHeight - 100;
      const viewport = getFitViewport(visibleUnlockedNodes, viewportWidth, viewportHeight, 0.1);
      reactFlow.setViewport(viewport, { duration: 500 });
    } else {
      reactFlow.fitView({ padding: 0.1, duration: 500 });
    }
  }, [reactFlow]);

  // Auto-focus search field when it becomes visible
  useEffect(() => {
    if (isSearchVisible && searchBarRef.current) {
      setTimeout(() => {
        searchBarRef.current?.focus();
      }, 100);
    }
  }, [isSearchVisible]);

  // Check if we should show the minimize button
  const isStandalone = !!settings.modeler?.standalone;
  const showMinimize = !isStandalone && settings.modeler?.stayInContextOnClose === true;

  // Build overflow items for the dropdown menu.
  // Handlers from useToolbarHandlers expect (e: React.MouseEvent) but the
  // overflow menu calls onClick() without an event.  We wrap them so they
  // can be invoked without arguments.
  const overflowItems = useMemo((): OverflowItem[] => {
    if (!showOverflowMenu) return [];

    const allItems: OverflowItem[] = [
      {
        id: 'search-toggle',
        icon: <FiSearch />,
        label: t('Search Elements'),
        onClick: () => onToggleSearch(),
        active: isSearchVisible,
      },
      {
        id: 'annotations',
        icon: <FiMessageSquare />,
        label: allAnnotationsVisible ? t('Hide All Annotations') : t('Show All Annotations'),
        onClick: () => onToggleAllAnnotations(),
        active: allAnnotationsVisible,
      },
      {
        id: 'edge-orders',
        icon: <FiHash />,
        label: edgeOrdersVisible ? t('Hide Edge Order Numbers') : t('Show Edge Order Numbers'),
        onClick: () => onToggleEdgeOrders(),
        active: edgeOrdersVisible,
      },
      {
        id: 'copy',
        icon: <FiCopy />,
        label: t('Copy'),
        onClick: () => onCopy(),
        disabled: isLocked || !hasSelection,
      },
      {
        id: 'paste',
        icon: <FiClipboard />,
        label: t('Paste'),
        onClick: () => onPaste(),
        disabled: isLocked || !canPaste,
      },
      {
        id: 'settings',
        icon: <FiSettings />,
        label: t('Model Settings'),
        onClick: () => onOpenMetadata(),
      },
      {
        id: 'zoom-in',
        icon: <FiZoomIn />,
        label: t('Zoom In'),
        onClick: directZoomIn,
        disabled: isAtMaxZoom(zoomLevel),
      },
      {
        id: 'zoom-out',
        icon: <FiZoomOut />,
        label: t('Zoom Out'),
        onClick: directZoomOut,
        disabled: isAtMinZoom(zoomLevel),
      },
      {
        id: 'fit-view',
        icon: <FiMaximize />,
        label: t('Fit View'),
        onClick: directFitView,
      },
      {
        id: 'auto-layout',
        icon: <FiLayout />,
        label: t('Auto Layout'),
        onClick: () => onAutoLayout(),
      },
      {
        id: 'lock',
        icon: isLocked ? <FiLock /> : <FiUnlock />,
        label: isLocked ? t('Unlock Canvas') : t('Lock Canvas'),
        onClick: () => onToggleLock(),
        active: isLocked,
      },
      {
        id: 'dark-mode',
        icon: darkMode ? <FiSun /> : <FiMoon />,
        label: darkMode ? t('Switch to Light Mode') : t('Switch to Dark Mode'),
        onClick: () => toggleDarkMode(),
        active: darkMode,
      },
      {
        id: 'minimap',
        icon: <FiMap />,
        label: isMinimapVisible ? t('Hide Minimap') : t('Show Minimap'),
        onClick: () => onToggleMinimap(),
        active: isMinimapVisible,
      },
      {
        id: 'documentation',
        icon: <FiBookOpen />,
        label: t('Documentation'),
        onClick: () => window.open('https://project.pages.drupalcode.org/modeler/', '_blank', 'noopener,noreferrer'),
      },
      ...(canExport && onExport ? [{
        id: 'export',
        icon: <FiDownload />,
        label: t('Export Model'),
        onClick: () => onExport(),
      }] : []),
    ];

    // In read-only mode, exclude editing-related items from the overflow menu
    const readOnlyHiddenIds = new Set(['copy', 'paste', 'auto-layout', 'lock']);
    return allItems.filter(item =>
      overflowedIds.has(item.id) && (!isReadOnly || !readOnlyHiddenIds.has(item.id))
    );
  }, [
    showOverflowMenu, overflowedIds, onToggleSearch, isSearchVisible,
    onToggleAllAnnotations, allAnnotationsVisible, onToggleEdgeOrders,
    edgeOrdersVisible, onCopy, isLocked, hasSelection, onPaste,
    canPaste, onOpenMetadata, directZoomIn, directZoomOut, zoomLevel,
    directFitView, onAutoLayout, onToggleLock, toggleDarkMode,
    darkMode, onToggleMinimap, isMinimapVisible, isReadOnly,
    canExport, onExport,
  ]);

  // Helper: returns 'toolbar-overflow-hidden' when the item is overflowed
  const oh = (id: string) => overflowedIds.has(id) ? ' toolbar-overflow-hidden' : '';

  // Helper: whether a separator group has at least one visible item
  const isGroupVisible = (...ids: string[]) => ids.some(id => !overflowedIds.has(id));

  return (
    <div className={`workflow-toolbar${compactMode ? ' toolbar-compact' : ''}`} ref={toolbarRef}>
      <div className="toolbar-left">
        {onAddEvent && !isLocked && !isReadOnly && (
          <QuickAddEventButton
            onAddEvent={onAddEvent}
            disabled={isLocked}
            isOpen={isEventPopupOpen}
            onOpenChange={onEventPopupOpenChange}
          />
        )}
        {contexts.length > 0 && (
          <select
            id="toolbar-context-select"
            name="toolbar-context-select"
            className="toolbar-context-select"
            value={selectedContextId ?? ''}
            onChange={(e) => onContextChange?.(e.target.value || null)}
            aria-label={t('Select Context')}
            title={t('Select Context')}
          >
            <option value="">{t('No Context')}</option>
            {contexts.map((ctx) => (
              <option key={ctx.id} value={ctx.id}>{ctx.topic}</option>
            ))}
          </select>
        )}
        <StartFlowFilter nodes={nodes} />
      </div>
      <div
        className="toolbar-center"
        onMouseDown={onStartDrag}
        onDoubleClick={onToggleViewMode}
      >
        <h1 className="model-title">
          {hasUnsavedChanges && <span className="unsaved-indicator">● </span>}
          {modelName}
        </h1>
        {hasMessages && (
          <div className="messages-actions">
            <button
              type="button"
              onClick={onToggleMessages}
              title={messagesVisible ? t('Hide messages') : t('Show messages')}
              aria-label={messagesVisible ? t('Hide messages') : t('Show messages')}
              className={`messages-toggle-btn ${messagesVisible ? 'inactive' : 'active'}`}
            >
              <FiZap />
            </button>
            <button
              type="button"
              onClick={onClearMessages}
              title={t('Clear messages')}
              aria-label={t('Clear messages')}
              className="messages-clear-btn"
            >
              <FiTrash2 />
            </button>
          </div>
        )}
      </div>

      <div className="toolbar-right" ref={toolbarRightRef}>
        <div
          className={`toolbar-search-wrapper${oh('search-toggle')}`}
          data-toolbar-id="search-toggle"
          data-toolbar-priority="3"
        >
          <button
            type="button"
            onClick={handleToggleSearch}
            title={t('Search Elements')}
            aria-label={t('Search Elements')}
            className={`toolbar-btn ${isSearchVisible ? 'active' : ''}`}
          >
            <FiSearch />
          </button>
          {isSearchVisible && (
            <div className="toolbar-search-popup">
              <SearchBar
                ref={searchBarRef}
                nodes={nodes}
                edges={edges}
                onHighlight={onSearchHighlight}
                onFocus={onSearchFocus}
              />
            </div>
          )}
        </div>
        <button
          type="button"
          onClick={onToggleAllAnnotations}
          title={allAnnotationsVisible ? t('Hide All Annotations') : t('Show All Annotations')}
          aria-label={allAnnotationsVisible ? t('Hide All Annotations') : t('Show All Annotations')}
          className={`toolbar-btn ${allAnnotationsVisible ? 'active' : ''}${oh('annotations')}`}
          data-toolbar-id="annotations"
          data-toolbar-priority="2"
        >
          <FiMessageSquare />
        </button>
        <button
          type="button"
          onClick={onToggleEdgeOrders}
          title={edgeOrdersVisible ? t('Hide Edge Order Numbers') : t('Show Edge Order Numbers')}
          aria-label={edgeOrdersVisible ? t('Hide Edge Order Numbers') : t('Show Edge Order Numbers')}
          className={`toolbar-btn ${edgeOrdersVisible ? 'active' : ''}${oh('edge-orders')}`}
          data-toolbar-id="edge-orders"
          data-toolbar-priority="2"
        >
          <FiHash />
        </button>
        {isGroupVisible('search-toggle', 'annotations', 'edge-orders') &&
          isGroupVisible('copy', 'paste') && (
          <div className="toolbar-separator" />
        )}
        {!isReadOnly && (
          <button
            type="button"
            onClick={handleCopy}
            title={t('Copy Selected Elements (Ctrl+C)')}
            aria-label={t('Copy Selected Elements (Ctrl+C)')}
            className={`toolbar-btn${oh('copy')}`}
            disabled={isLocked || !hasSelection}
            data-toolbar-id="copy"
            data-toolbar-priority="2"
          >
            <FiCopy />
          </button>
        )}
        {!isReadOnly && (
          <button
            type="button"
            onClick={handlePaste}
            title={t('Paste Elements (Ctrl+V)')}
            aria-label={t('Paste Elements (Ctrl+V)')}
            className={`toolbar-btn${oh('paste')}`}
            disabled={isLocked || !canPaste}
            data-toolbar-id="paste"
            data-toolbar-priority="2"
          >
            <FiClipboard />
          </button>
        )}
        {isGroupVisible('copy', 'paste') &&
          isGroupVisible('settings', 'zoom-in', 'zoom-out', 'fit-view', 'auto-layout', 'lock', 'dark-mode', 'minimap') && (
          <div className="toolbar-separator" />
        )}
        <button
          type="button"
          onClick={onOpenMetadata}
          title={t('Model Settings')}
          aria-label={t('Model Settings')}
          className={`toolbar-btn${oh('settings')}`}
          data-toolbar-id="settings"
          data-toolbar-priority="3"
        >
          <FiSettings />
        </button>
        <button
          type="button"
          onClick={handleZoomIn}
          title={t('Zoom In')}
          aria-label={t('Zoom In')}
          className={`toolbar-btn${oh('zoom-in')}`}
          disabled={isAtMaxZoom(zoomLevel)}
          data-toolbar-id="zoom-in"
          data-toolbar-priority="1"
        >
          <FiZoomIn />
        </button>
        <button
          type="button"
          onClick={handleZoomOut}
          title={t('Zoom Out')}
          aria-label={t('Zoom Out')}
          className={`toolbar-btn${oh('zoom-out')}`}
          disabled={isAtMinZoom(zoomLevel)}
          data-toolbar-id="zoom-out"
          data-toolbar-priority="1"
        >
          <FiZoomOut />
        </button>
        <button
          type="button"
          onClick={handleFitView}
          title={t('Fit View')}
          aria-label={t('Fit View')}
          className={`toolbar-btn${oh('fit-view')}`}
          data-toolbar-id="fit-view"
          data-toolbar-priority="1"
        >
          <FiMaximize />
        </button>
        {!isReadOnly && (
          <button
            type="button"
            onClick={handleAutoLayout}
            title={t('Auto Layout')}
            aria-label={t('Auto Layout')}
            className={`toolbar-btn${oh('auto-layout')}`}
            data-toolbar-id="auto-layout"
            data-toolbar-priority="1"
          >
            <FiLayout />
          </button>
        )}
        {!isReadOnly && (
          <button
            type="button"
            onClick={handleToggleLock}
            title={isLocked ? t('Unlock Canvas') : t('Lock Canvas')}
            aria-label={isLocked ? t('Unlock Canvas') : t('Lock Canvas')}
            className={`toolbar-btn ${isLocked ? 'active' : ''}${oh('lock')}`}
            data-toolbar-id="lock"
            data-toolbar-priority="2"
          >
            {isLocked ? <FiLock /> : <FiUnlock />}
          </button>
        )}
        <button
          type="button"
          onClick={toggleDarkMode}
          title={darkMode ? t('Switch to Light Mode') : t('Switch to Dark Mode')}
          aria-label={darkMode ? t('Switch to Light Mode') : t('Switch to Dark Mode')}
          className={`toolbar-btn ${darkMode ? 'active' : ''}${oh('dark-mode')}`}
          data-toolbar-id="dark-mode"
          data-toolbar-priority="1"
        >
          {darkMode ? <FiSun /> : <FiMoon />}
        </button>
        <button
          type="button"
          onClick={onToggleMinimap}
          title={isMinimapVisible ? t('Hide Minimap') : t('Show Minimap')}
          aria-label={isMinimapVisible ? t('Hide Minimap') : t('Show Minimap')}
          className={`toolbar-btn ${isMinimapVisible ? 'active' : ''}${oh('minimap')}`}
          data-toolbar-id="minimap"
          data-toolbar-priority="1"
        >
          <FiMap />
        </button>
        <a
          href="https://project.pages.drupalcode.org/modeler/"
          target="_blank"
          rel="noopener noreferrer"
          title={t('Documentation')}
          aria-label={t('Documentation')}
          className={`toolbar-btn${oh('documentation')}`}
          data-toolbar-id="documentation"
          data-toolbar-priority="1"
        >
          <FiBookOpen />
        </a>
        {isGroupVisible('settings', 'zoom-in', 'zoom-out', 'fit-view', 'auto-layout', 'lock', 'dark-mode', 'minimap', 'documentation') && (
          <div className="toolbar-separator" />
        )}
        {showOverflowMenu && (
          <ToolbarOverflowMenu items={overflowItems} />
        )}
        {canExport && onExport && (
          <button
            type="button"
            onClick={onExport}
            title={t('Export Model')}
            aria-label={t('Export Model')}
            className={`toolbar-btn${oh('export')}`}
            data-toolbar-id="export"
            data-toolbar-priority="2"
          >
            <FiDownload />
          </button>
        )}
        {!isReadOnly && (
          <button
            type="button"
            ref={saveButtonRef}
            onClick={handleSave}
            title={t('Save Model')}
            className="toolbar-btn primary"
            disabled={!hasUnsavedChanges}
          >
            <FiSave /> {t('Save')}
          </button>
        )}
        {onToggleViewMode && (
          <button
            type="button"
            onClick={onToggleViewMode}
            title={viewMode === 'fullscreen' ? t('Restore Window') : t('Fullscreen')}
            aria-label={viewMode === 'fullscreen' ? t('Restore Window') : t('Fullscreen')}
            className="toolbar-btn"
          >
            {viewMode === 'fullscreen' ? <FiMinimize2 /> : <FiMaximize2 />}
          </button>
        )}
        {showMinimize && (
          <button
            type="button"
            onClick={handleMinimize}
            title={t('Minimize Modeler')}
            aria-label={t('Minimize Modeler')}
            className="toolbar-btn"
          >
            <FiMinus />
          </button>
        )}
        {!isStandalone && (
          <button
            type="button"
            onClick={handleClose}
            title={t('Close Modeler')}
            aria-label={t('Close Modeler')}
            className="toolbar-btn"
          >
            <FiX />
          </button>
        )}
      </div>
    </div>
  );
};

export default Toolbar;
