import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import Toolbar from '../Toolbar';

// Mock reactflow
jest.mock('reactflow', () => ({
  useReactFlow: () => ({
    zoomIn: jest.fn(),
    zoomOut: jest.fn(),
    fitView: jest.fn(),
    setViewport: jest.fn(),
    getNodes: () => [],
  }),
}));

// Mock SearchBar
jest.mock('../SearchBar', () => {
  const MockSearchBar = React.forwardRef<any, any>((_props, _ref) => (
    <div data-testid="search-bar">SearchBar</div>
  ));
  MockSearchBar.displayName = 'SearchBar';
  return MockSearchBar;
});

// Mock StartFlowFilter
jest.mock('../StartFlowFilter', () => {
  const MockStartFlowFilter = (props: any) => (
    <div data-testid="start-flow-filter" data-node-count={props.nodes?.length ?? 0}>StartFlowFilter</div>
  );
  MockStartFlowFilter.displayName = 'StartFlowFilter';
  return { __esModule: true, default: MockStartFlowFilter };
});

// Mock modelUtils
jest.mock('../../utils/modelUtils', () => ({
  getFitViewport: jest.fn(() => ({ x: 0, y: 0, zoom: 1 })),
}));

// Mock store
jest.mock('../../store/store', () => ({
  useStore: jest.fn((selector) => {
    const state = {
      darkMode: false,
      toggleDarkMode: jest.fn(),
    };
    if (typeof selector === 'function') return selector(state);
    return state;
  }),
}));

describe('Toolbar', () => {
  const defaultProps = {
    onSave: jest.fn(),
    onOpenMetadata: jest.fn(),
    onToggleLock: jest.fn(),
    onAutoLayout: jest.fn(),
    onCopy: jest.fn(),
    onPaste: jest.fn(),
    onToggleSearch: jest.fn(),
    onToggleAllAnnotations: jest.fn(),
     onToggleMessages: jest.fn(),
    onClearMessages: jest.fn(),
    onToggleMinimap: jest.fn(),
    onToggleEdgeOrders: jest.fn(),
    isLocked: false,
    isSearchVisible: false,
    isMinimapVisible: false,
    hasSelection: false,
    canPaste: false,
    nodes: [],
    edges: [],
    allAnnotationsVisible: false,
    edgeOrdersVisible: false,
    hasMessages: false,
    messagesVisible: false,
    zoomLevel: 1,
    modelName: 'Test Model',
    hasUnsavedChanges: false,
    onClose: jest.fn(),
    onMinimize: jest.fn(),
    settings: {},
    drupal: undefined,
  };

  beforeEach(() => {
    jest.clearAllMocks();
    // Mock jQuery for save button tests
    (window as any).jQuery = undefined;
  });

  describe('rendering', () => {
    it('should render toolbar container', () => {
      render(<Toolbar {...defaultProps} />);
      expect(document.querySelector('.workflow-toolbar')).toBeInTheDocument();
    });

    it('should render save button', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.getByTitle('Save Model')).toBeInTheDocument();
    });

    it('should render settings button', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.getByTitle('Model Settings')).toBeInTheDocument();
    });

    it('should render copy button', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.getByTitle('Copy Selected Elements (Ctrl+C)')).toBeInTheDocument();
    });

    it('should render paste button', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.getByTitle('Paste Elements (Ctrl+V)')).toBeInTheDocument();
    });

    it('should render model name', () => {
      render(<Toolbar {...defaultProps} modelName="My Model" />);
      expect(screen.getByText('My Model')).toBeInTheDocument();
    });

    it('should render zoom in button', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.getByTitle('Zoom In')).toBeInTheDocument();
    });

    it('should render zoom out button', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.getByTitle('Zoom Out')).toBeInTheDocument();
    });

    it('should render fit view button', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.getByTitle('Fit View')).toBeInTheDocument();
    });

    it('should render auto layout button', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.getByTitle('Auto Layout')).toBeInTheDocument();
    });

    it('should render lock button', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.getByTitle('Lock Canvas')).toBeInTheDocument();
    });

    it('should render minimap toggle button', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.getByTitle('Show Minimap')).toBeInTheDocument();
    });

    it('should render close button', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.getByTitle('Close Modeler')).toBeInTheDocument();
    });
  });

  describe('unsaved changes indicator', () => {
    it('should show unsaved indicator when hasUnsavedChanges is true', () => {
      render(<Toolbar {...defaultProps} hasUnsavedChanges={true} />);
      expect(document.querySelector('.unsaved-indicator')).toBeInTheDocument();
    });

    it('should not show unsaved indicator when hasUnsavedChanges is false', () => {
      render(<Toolbar {...defaultProps} hasUnsavedChanges={false} />);
      expect(document.querySelector('.unsaved-indicator')).not.toBeInTheDocument();
    });
  });

  describe('button states', () => {
    it('should disable copy button when locked', () => {
      render(<Toolbar {...defaultProps} isLocked={true} />);
      expect(screen.getByTitle('Copy Selected Elements (Ctrl+C)')).toBeDisabled();
    });

    it('should disable copy button when no selection', () => {
      render(<Toolbar {...defaultProps} hasSelection={false} />);
      expect(screen.getByTitle('Copy Selected Elements (Ctrl+C)')).toBeDisabled();
    });

    it('should enable copy button when unlocked and has selection', () => {
      render(<Toolbar {...defaultProps} isLocked={false} hasSelection={true} />);
      expect(screen.getByTitle('Copy Selected Elements (Ctrl+C)')).not.toBeDisabled();
    });

    it('should disable paste button when locked', () => {
      render(<Toolbar {...defaultProps} isLocked={true} canPaste={true} />);
      expect(screen.getByTitle('Paste Elements (Ctrl+V)')).toBeDisabled();
    });

    it('should disable paste button when canPaste is false', () => {
      render(<Toolbar {...defaultProps} canPaste={false} />);
      expect(screen.getByTitle('Paste Elements (Ctrl+V)')).toBeDisabled();
    });

    it('should enable paste button when unlocked and canPaste is true', () => {
      render(<Toolbar {...defaultProps} isLocked={false} canPaste={true} />);
      expect(screen.getByTitle('Paste Elements (Ctrl+V)')).not.toBeDisabled();
    });

    it('should disable zoom in at max zoom', () => {
      render(<Toolbar {...defaultProps} zoomLevel={4} />);
      expect(screen.getByTitle('Zoom In')).toBeDisabled();
    });

    it('should disable zoom out at min zoom', () => {
      render(<Toolbar {...defaultProps} zoomLevel={0.1} />);
      expect(screen.getByTitle('Zoom Out')).toBeDisabled();
    });
  });

  describe('lock button state', () => {
    it('should show "Lock Canvas" when unlocked', () => {
      render(<Toolbar {...defaultProps} isLocked={false} />);
      expect(screen.getByTitle('Lock Canvas')).toBeInTheDocument();
    });

    it('should show "Unlock Canvas" when locked', () => {
      render(<Toolbar {...defaultProps} isLocked={true} />);
      expect(screen.getByTitle('Unlock Canvas')).toBeInTheDocument();
    });

    it('should have active class when locked', () => {
      render(<Toolbar {...defaultProps} isLocked={true} />);
      expect(screen.getByTitle('Unlock Canvas')).toHaveClass('active');
    });
  });

  describe('button click handlers', () => {
    it('should call onOpenMetadata when settings clicked', () => {
      const onOpenMetadata = jest.fn();
      render(<Toolbar {...defaultProps} onOpenMetadata={onOpenMetadata} />);

      fireEvent.click(screen.getByTitle('Model Settings'));

      expect(onOpenMetadata).toHaveBeenCalled();
    });

    it('should call onCopy when copy clicked', () => {
      const onCopy = jest.fn();
      render(<Toolbar {...defaultProps} onCopy={onCopy} hasSelection={true} />);

      fireEvent.click(screen.getByTitle('Copy Selected Elements (Ctrl+C)'));

      expect(onCopy).toHaveBeenCalled();
    });

    it('should call onPaste when paste clicked', () => {
      const onPaste = jest.fn();
      render(<Toolbar {...defaultProps} onPaste={onPaste} canPaste={true} />);

      fireEvent.click(screen.getByTitle('Paste Elements (Ctrl+V)'));

      expect(onPaste).toHaveBeenCalled();
    });

    it('should call onToggleLock when lock clicked', () => {
      const onToggleLock = jest.fn();
      render(<Toolbar {...defaultProps} onToggleLock={onToggleLock} />);

      fireEvent.click(screen.getByTitle('Lock Canvas'));

      expect(onToggleLock).toHaveBeenCalled();
    });

    it('should call onAutoLayout when auto layout clicked', () => {
      const onAutoLayout = jest.fn();
      render(<Toolbar {...defaultProps} onAutoLayout={onAutoLayout} />);

      fireEvent.click(screen.getByTitle('Auto Layout'));

      expect(onAutoLayout).toHaveBeenCalled();
    });

    it('should call onToggleSearch when search clicked', () => {
      const onToggleSearch = jest.fn();
      render(<Toolbar {...defaultProps} onToggleSearch={onToggleSearch} />);

      fireEvent.click(screen.getByTitle('Search Elements'));

      expect(onToggleSearch).toHaveBeenCalled();
    });

    it('should call onToggleAllAnnotations when annotations clicked', () => {
      const onToggleAllAnnotations = jest.fn();
      render(<Toolbar {...defaultProps} onToggleAllAnnotations={onToggleAllAnnotations} />);

      fireEvent.click(screen.getByTitle('Show All Annotations'));

      expect(onToggleAllAnnotations).toHaveBeenCalled();
    });

    it('should call onToggleMinimap when minimap clicked', () => {
      const onToggleMinimap = jest.fn();
      render(<Toolbar {...defaultProps} onToggleMinimap={onToggleMinimap} />);

      fireEvent.click(screen.getByTitle('Show Minimap'));

      expect(onToggleMinimap).toHaveBeenCalled();
    });

    it('should call onToggleEdgeOrders when edge orders clicked', () => {
      const onToggleEdgeOrders = jest.fn();
      render(<Toolbar {...defaultProps} onToggleEdgeOrders={onToggleEdgeOrders} />);

      fireEvent.click(screen.getByTitle('Show Edge Order Numbers'));

      expect(onToggleEdgeOrders).toHaveBeenCalled();
    });

    it('should call onClose when close clicked', () => {
      const onClose = jest.fn();
      render(<Toolbar {...defaultProps} onClose={onClose} />);

      fireEvent.click(screen.getByTitle('Close Modeler'));

      expect(onClose).toHaveBeenCalled();
    });
  });

  describe('search bar visibility', () => {
    it('should show search bar when isSearchVisible is true', () => {
      render(<Toolbar {...defaultProps} isSearchVisible={true} />);
      expect(screen.getByTestId('search-bar')).toBeInTheDocument();
    });

    it('should hide search bar when isSearchVisible is false', () => {
      render(<Toolbar {...defaultProps} isSearchVisible={false} />);
      expect(screen.queryByTestId('search-bar')).not.toBeInTheDocument();
    });

    it('should have active class on search button when visible', () => {
      render(<Toolbar {...defaultProps} isSearchVisible={true} />);
      expect(screen.getByTitle('Search Elements')).toHaveClass('active');
    });
  });

  describe('annotations toggle state', () => {
    it('should show "Show All Annotations" when not visible', () => {
      render(<Toolbar {...defaultProps} allAnnotationsVisible={false} />);
      expect(screen.getByTitle('Show All Annotations')).toBeInTheDocument();
    });

    it('should show "Hide All Annotations" when visible', () => {
      render(<Toolbar {...defaultProps} allAnnotationsVisible={true} />);
      expect(screen.getByTitle('Hide All Annotations')).toBeInTheDocument();
    });

    it('should have active class when annotations visible', () => {
      render(<Toolbar {...defaultProps} allAnnotationsVisible={true} />);
      expect(screen.getByTitle('Hide All Annotations')).toHaveClass('active');
    });
  });

  describe('minimap toggle state', () => {
    it('should show "Show Minimap" when not visible', () => {
      render(<Toolbar {...defaultProps} isMinimapVisible={false} />);
      expect(screen.getByTitle('Show Minimap')).toBeInTheDocument();
    });

    it('should show "Hide Minimap" when visible', () => {
      render(<Toolbar {...defaultProps} isMinimapVisible={true} />);
      expect(screen.getByTitle('Hide Minimap')).toBeInTheDocument();
    });

    it('should have active class when minimap visible', () => {
      render(<Toolbar {...defaultProps} isMinimapVisible={true} />);
      expect(screen.getByTitle('Hide Minimap')).toHaveClass('active');
    });
  });

  describe('edge orders toggle state', () => {
    it('should show "Show Edge Order Numbers" when not visible', () => {
      render(<Toolbar {...defaultProps} edgeOrdersVisible={false} />);
      expect(screen.getByTitle('Show Edge Order Numbers')).toBeInTheDocument();
    });

    it('should show "Hide Edge Order Numbers" when visible', () => {
      render(<Toolbar {...defaultProps} edgeOrdersVisible={true} />);
      expect(screen.getByTitle('Hide Edge Order Numbers')).toBeInTheDocument();
    });

    it('should have active class when edge orders visible', () => {
      render(<Toolbar {...defaultProps} edgeOrdersVisible={true} />);
      expect(screen.getByTitle('Hide Edge Order Numbers')).toHaveClass('active');
    });
  });

  describe('minimize button', () => {
    it('should not show minimize button by default', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.queryByTitle('Minimize Modeler')).not.toBeInTheDocument();
    });

    it('should show minimize button when stayInContextOnClose is true', () => {
      render(
        <Toolbar
          {...defaultProps}
          settings={{ modeler: { stayInContextOnClose: true } }}
        />
      );
      expect(screen.getByTitle('Minimize Modeler')).toBeInTheDocument();
    });

    it('should call onMinimize when minimize clicked', () => {
      const onMinimize = jest.fn();
      render(
        <Toolbar
          {...defaultProps}
          onMinimize={onMinimize}
          settings={{ modeler: { stayInContextOnClose: true } }}
        />
      );

      fireEvent.click(screen.getByTitle('Minimize Modeler'));

      expect(onMinimize).toHaveBeenCalled();
    });
  });

  describe('messages toggle', () => {
    it('should not show messages toggle when hasMessages is false', () => {
      render(<Toolbar {...defaultProps} hasMessages={false} />);
      expect(screen.queryByTitle('Show messages')).not.toBeInTheDocument();
    });

    it('should show messages toggle when hasMessages is true', () => {
      render(<Toolbar {...defaultProps} hasMessages={true} />);
      expect(screen.getByTitle('Show messages')).toBeInTheDocument();
    });

    it('should call onToggleMessages when clicked', () => {
      const onToggleMessages = jest.fn();
      render(
        <Toolbar
          {...defaultProps}
          hasMessages={true}
          onToggleMessages={onToggleMessages}
        />
      );

      fireEvent.click(screen.getByTitle('Show messages'));

      expect(onToggleMessages).toHaveBeenCalled();
    });

    it('should show "Hide messages" tooltip when messages are visible', () => {
      render(
        <Toolbar
          {...defaultProps}
          hasMessages={true}
          messagesVisible={true}
        />
      );
      expect(screen.getByTitle('Hide messages')).toBeInTheDocument();
    });

    it('should show "Show messages" tooltip when messages are hidden', () => {
      render(
        <Toolbar
          {...defaultProps}
          hasMessages={true}
          messagesVisible={false}
        />
      );
      expect(screen.getByTitle('Show messages')).toBeInTheDocument();
    });

    it('should apply inactive class when messages are visible', () => {
      render(
        <Toolbar
          {...defaultProps}
          hasMessages={true}
          messagesVisible={true}
        />
      );
      const button = screen.getByTitle('Hide messages');
      expect(button.classList.contains('inactive')).toBe(true);
    });

    it('should apply active class when messages are hidden', () => {
      render(
        <Toolbar
          {...defaultProps}
          hasMessages={true}
          messagesVisible={false}
        />
      );
      const button = screen.getByTitle('Show messages');
      expect(button.classList.contains('active')).toBe(true);
    });

    it('should show clear button when hasMessages is true', () => {
      render(<Toolbar {...defaultProps} hasMessages={true} />);
      expect(screen.getByTitle('Clear messages')).toBeInTheDocument();
    });

    it('should not show clear button when hasMessages is false', () => {
      render(<Toolbar {...defaultProps} hasMessages={false} />);
      expect(screen.queryByTitle('Clear messages')).not.toBeInTheDocument();
    });

    it('should call onClearMessages when clear button is clicked', () => {
      const onClearMessages = jest.fn();
      render(
        <Toolbar
          {...defaultProps}
          hasMessages={true}
          onClearMessages={onClearMessages}
        />
      );

      fireEvent.click(screen.getByTitle('Clear messages'));

      expect(onClearMessages).toHaveBeenCalled();
    });
  });

  describe('save button', () => {
    it('should be disabled when hasUnsavedChanges is false', () => {
      render(<Toolbar {...defaultProps} hasUnsavedChanges={false} />);
      expect(screen.getByTitle('Save Model')).toBeDisabled();
    });

    it('should be enabled when hasUnsavedChanges is true', () => {
      render(<Toolbar {...defaultProps} hasUnsavedChanges={true} />);
      expect(screen.getByTitle('Save Model')).not.toBeDisabled();
    });

    it('should handle save click without drupal object', () => {
      const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
      render(<Toolbar {...defaultProps} hasUnsavedChanges={true} />);

      fireEvent.click(screen.getByTitle('Save Model'));

      expect(consoleSpy).toHaveBeenCalledWith('Drupal object not available');
      consoleSpy.mockRestore();
    });

    it('should handle save click with drupal but no model data', () => {
      const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
      const mockDrupal = { ajax: jest.fn() };
      const onSave = jest.fn().mockReturnValue(null);

      render(<Toolbar {...defaultProps} drupal={mockDrupal} onSave={onSave} hasUnsavedChanges={true} />);

      fireEvent.click(screen.getByTitle('Save Model'));

      expect(consoleSpy).toHaveBeenCalledWith('No model data available to save');
      consoleSpy.mockRestore();
    });

    it('should handle save with model data but missing modeler_api settings', () => {
      const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
      const mockDrupal = { ajax: jest.fn() };
      const onSave = jest.fn().mockReturnValue({ nodes: [], edges: [] });

      render(
        <Toolbar
          {...defaultProps}
          drupal={mockDrupal}
          onSave={onSave}
          settings={{}}
          hasUnsavedChanges={true}
        />
      );

      fireEvent.click(screen.getByTitle('Save Model'));

      expect(consoleSpy).toHaveBeenCalledWith('modeler_api settings not found');
      consoleSpy.mockRestore();
    });

    it('should handle save with missing save_url', () => {
      const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
      const mockDrupal = { ajax: jest.fn() };
      const onSave = jest.fn().mockReturnValue({ nodes: [], edges: [] });

      render(
        <Toolbar
          {...defaultProps}
          drupal={mockDrupal}
          onSave={onSave}
          settings={{ modeler_api: { token_url: '/token' } }}
          hasUnsavedChanges={true}
        />
      );

      fireEvent.click(screen.getByTitle('Save Model'));

      expect(consoleSpy).toHaveBeenCalledWith('Missing modeler API URLs');
      consoleSpy.mockRestore();
    });

    it('should handle save with missing token_url', () => {
      const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
      const mockDrupal = { ajax: jest.fn() };
      const onSave = jest.fn().mockReturnValue({ nodes: [], edges: [] });

      render(
        <Toolbar
          {...defaultProps}
          drupal={mockDrupal}
          onSave={onSave}
          settings={{ modeler_api: { save_url: '/save' } }}
          hasUnsavedChanges={true}
        />
      );

      fireEvent.click(screen.getByTitle('Save Model'));

      expect(consoleSpy).toHaveBeenCalledWith('Missing modeler API URLs');
      consoleSpy.mockRestore();
    });

    it('should handle save when jQuery is not available', () => {
      const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
      const mockDrupal = { ajax: jest.fn() };
      const onSave = jest.fn().mockReturnValue({ nodes: [], edges: [] });
      (window as any).jQuery = undefined;

      render(
        <Toolbar
          {...defaultProps}
          drupal={mockDrupal}
          onSave={onSave}
          settings={{ modeler_api: { token_url: '/token', save_url: '/save' } }}
          hasUnsavedChanges={true}
        />
      );

      fireEvent.click(screen.getByTitle('Save Model'));

      expect(consoleSpy).toHaveBeenCalledWith('jQuery not available');
      consoleSpy.mockRestore();
    });

    it('should use workflowModelerData when onSave returns null', () => {
      const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
      const mockDrupal = { ajax: jest.fn() };
      const onSave = jest.fn().mockReturnValue(null);
      (window as any).workflowModelerData = { test: 'data' };
      (window as any).jQuery = undefined;

      render(
        <Toolbar
          {...defaultProps}
          drupal={mockDrupal}
          onSave={onSave}
          settings={{ modeler_api: { token_url: '/token', save_url: '/save' } }}
          hasUnsavedChanges={true}
        />
      );

      fireEvent.click(screen.getByTitle('Save Model'));

      // Should proceed past the model data check and fail on jQuery
      expect(consoleSpy).toHaveBeenCalledWith('jQuery not available');
      consoleSpy.mockRestore();
      delete (window as any).workflowModelerData;
    });


  });

  describe('fit view button', () => {
    it('should call fitView when clicked', () => {
      render(<Toolbar {...defaultProps} />);

      fireEvent.click(screen.getByTitle('Fit View'));

      // The mock should be called
      const { fitView } = require('reactflow').useReactFlow();
      expect(fitView).toBeDefined();
    });
  });

  describe('zoom buttons at limits', () => {
    it('should enable zoom in when not at max zoom', () => {
      render(<Toolbar {...defaultProps} zoomLevel={2} />);
      expect(screen.getByTitle('Zoom In')).not.toBeDisabled();
    });

    it('should enable zoom out when not at min zoom', () => {
      render(<Toolbar {...defaultProps} zoomLevel={1} />);
      expect(screen.getByTitle('Zoom Out')).not.toBeDisabled();
    });
  });

  describe('onDeleteNode not clearing selection', () => {
    it('should not clear selection if different node was selected', () => {
      // This would be a hook test, but we test it via Toolbar integration
      // The actual implementation is tested through the Toolbar component behavior
    });
  });

  describe('start flow filter', () => {
    it('should render StartFlowFilter in toolbar', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.getByTestId('start-flow-filter')).toBeInTheDocument();
    });

    it('should pass nodes prop to StartFlowFilter', () => {
      const nodes = [
        { id: 'n1', type: 'start', position: { x: 0, y: 0 }, data: {} },
        { id: 'n2', type: 'start', position: { x: 1, y: 0 }, data: {} },
      ];
      render(<Toolbar {...defaultProps} nodes={nodes} />);
      expect(screen.getByTestId('start-flow-filter').getAttribute('data-node-count')).toBe('2');
    });
  });

  describe('context selector', () => {
    const mockContexts = [
      { id: 'ctx_1', topic: 'Content Editing', model_owner: 'test_owner', components: {} },
      { id: 'ctx_2', topic: 'User Management', model_owner: 'test_owner', components: {} },
    ];

    it('should not render context selector when contexts is empty', () => {
      render(<Toolbar {...defaultProps} contexts={[]} />);
      expect(screen.queryByTitle('Select Context')).not.toBeInTheDocument();
    });

    it('should not render context selector when contexts is undefined', () => {
      render(<Toolbar {...defaultProps} />);
      expect(screen.queryByTitle('Select Context')).not.toBeInTheDocument();
    });

    it('should render context selector when contexts are provided', () => {
      render(<Toolbar {...defaultProps} contexts={mockContexts} />);
      expect(screen.getByTitle('Select Context')).toBeInTheDocument();
    });

    it('should render "No Context" as the first option', () => {
      render(<Toolbar {...defaultProps} contexts={mockContexts} />);
      const select = screen.getByTitle('Select Context') as HTMLSelectElement;
      expect(select.options[0].textContent).toBe('No Context');
      expect(select.options[0].value).toBe('');
    });

    it('should render all context topics as options', () => {
      render(<Toolbar {...defaultProps} contexts={mockContexts} />);
      const select = screen.getByTitle('Select Context') as HTMLSelectElement;
      expect(select.options).toHaveLength(3); // "No Context" + 2 contexts
      expect(select.options[1].textContent).toBe('Content Editing');
      expect(select.options[2].textContent).toBe('User Management');
    });

    it('should show "No Context" selected when selectedContextId is null', () => {
      render(<Toolbar {...defaultProps} contexts={mockContexts} selectedContextId={null} />);
      const select = screen.getByTitle('Select Context') as HTMLSelectElement;
      expect(select.value).toBe('');
    });

    it('should show correct context selected', () => {
      render(<Toolbar {...defaultProps} contexts={mockContexts} selectedContextId="ctx_2" />);
      const select = screen.getByTitle('Select Context') as HTMLSelectElement;
      expect(select.value).toBe('ctx_2');
    });

    it('should call onContextChange with context id when a context is selected', () => {
      const onContextChange = jest.fn();
      render(
        <Toolbar
          {...defaultProps}
          contexts={mockContexts}
          selectedContextId={null}
          onContextChange={onContextChange}
        />
      );
      const select = screen.getByTitle('Select Context') as HTMLSelectElement;
      fireEvent.change(select, { target: { value: 'ctx_1' } });
      expect(onContextChange).toHaveBeenCalledWith('ctx_1');
    });

    it('should call onContextChange with null when "No Context" is selected', () => {
      const onContextChange = jest.fn();
      render(
        <Toolbar
          {...defaultProps}
          contexts={mockContexts}
          selectedContextId="ctx_1"
          onContextChange={onContextChange}
        />
      );
      const select = screen.getByTitle('Select Context') as HTMLSelectElement;
      fireEvent.change(select, { target: { value: '' } });
      expect(onContextChange).toHaveBeenCalledWith(null);
    });

    it('should have proper aria-label for accessibility', () => {
      render(<Toolbar {...defaultProps} contexts={mockContexts} />);
      expect(screen.getByLabelText('Select Context')).toBeInTheDocument();
    });
  });

  describe('read-only mode', () => {
    it('should hide save button when isReadOnly is true', () => {
      render(<Toolbar {...defaultProps} isReadOnly={true} />);
      expect(screen.queryByTitle('Save Model')).not.toBeInTheDocument();
    });

    it('should hide copy button when isReadOnly is true', () => {
      render(<Toolbar {...defaultProps} isReadOnly={true} />);
      expect(screen.queryByTitle('Copy Selected Elements (Ctrl+C)')).not.toBeInTheDocument();
    });

    it('should hide paste button when isReadOnly is true', () => {
      render(<Toolbar {...defaultProps} isReadOnly={true} />);
      expect(screen.queryByTitle('Paste Elements (Ctrl+V)')).not.toBeInTheDocument();
    });

    it('should hide auto layout button when isReadOnly is true', () => {
      render(<Toolbar {...defaultProps} isReadOnly={true} />);
      expect(screen.queryByTitle('Auto Layout')).not.toBeInTheDocument();
    });

    it('should hide lock toggle button when isReadOnly is true', () => {
      render(<Toolbar {...defaultProps} isReadOnly={true} />);
      expect(screen.queryByTitle('Lock Canvas')).not.toBeInTheDocument();
      expect(screen.queryByTitle('Unlock Canvas')).not.toBeInTheDocument();
    });

    it('should still show settings button when isReadOnly is true', () => {
      render(<Toolbar {...defaultProps} isReadOnly={true} />);
      expect(screen.getByTitle('Model Settings')).toBeInTheDocument();
    });

    it('should still show zoom buttons when isReadOnly is true', () => {
      render(<Toolbar {...defaultProps} isReadOnly={true} />);
      expect(screen.getByTitle('Zoom In')).toBeInTheDocument();
      expect(screen.getByTitle('Zoom Out')).toBeInTheDocument();
      expect(screen.getByTitle('Fit View')).toBeInTheDocument();
    });

    it('should still show search button when isReadOnly is true', () => {
      render(<Toolbar {...defaultProps} isReadOnly={true} />);
      expect(screen.getByTitle('Search Elements')).toBeInTheDocument();
    });

    it('should still show dark mode button when isReadOnly is true', () => {
      render(<Toolbar {...defaultProps} isReadOnly={true} />);
      expect(screen.getByTitle('Switch to Dark Mode')).toBeInTheDocument();
    });

    it('should still show minimap button when isReadOnly is true', () => {
      render(<Toolbar {...defaultProps} isReadOnly={true} />);
      expect(screen.getByTitle('Show Minimap')).toBeInTheDocument();
    });

    it('should still show close button when isReadOnly is true', () => {
      render(<Toolbar {...defaultProps} isReadOnly={true} />);
      expect(screen.getByTitle('Close Modeler')).toBeInTheDocument();
    });

    it('should still show annotations toggle when isReadOnly is true', () => {
      render(<Toolbar {...defaultProps} isReadOnly={true} />);
      expect(screen.getByTitle('Show All Annotations')).toBeInTheDocument();
    });

    it('should hide quick-add event button when isReadOnly is true', () => {
      const onAddEvent = jest.fn();
      render(<Toolbar {...defaultProps} isReadOnly={true} onAddEvent={onAddEvent} />);
      expect(screen.queryByText('New event')).not.toBeInTheDocument();
    });

    it('should show all editing buttons when isReadOnly is false', () => {
      render(<Toolbar {...defaultProps} isReadOnly={false} />);
      expect(screen.getByTitle('Save Model')).toBeInTheDocument();
      expect(screen.getByTitle('Copy Selected Elements (Ctrl+C)')).toBeInTheDocument();
      expect(screen.getByTitle('Paste Elements (Ctrl+V)')).toBeInTheDocument();
      expect(screen.getByTitle('Auto Layout')).toBeInTheDocument();
      expect(screen.getByTitle('Lock Canvas')).toBeInTheDocument();
    });
  });
});
