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

// Mock react-icons
jest.mock('react-icons/fi', () => ({
  FiMoreHorizontal: () => <span data-testid="fi-more-horizontal" />,
  FiSearch: () => <span data-testid="fi-search" />,
  FiSettings: () => <span data-testid="fi-settings" />,
}));

const FiSearch = () => <span data-testid="fi-search" />;
const FiSettings = () => <span data-testid="fi-settings" />;

function makeItems(overrides: Partial<OverflowItem>[] = []): OverflowItem[] {
  const defaults: OverflowItem[] = [
    { id: 'search', icon: <FiSearch />, label: 'Search Elements', onClick: jest.fn() },
    { id: 'settings', icon: <FiSettings />, label: 'Model Settings', onClick: jest.fn() },
  ];
  if (overrides.length) {
    return overrides.map((o, i) => ({ ...defaults[i % defaults.length], ...o }));
  }
  return defaults;
}

describe('ToolbarOverflowMenu', () => {
  it('renders nothing when items is empty', () => {
    const { container } = render(<ToolbarOverflowMenu items={[]} />);
    expect(container.innerHTML).toBe('');
  });

  it('renders the trigger button with correct aria attributes', () => {
    render(<ToolbarOverflowMenu items={makeItems()} />);
    const trigger = screen.getByTitle('More toolbar actions');
    expect(trigger).toBeInTheDocument();
    expect(trigger).toHaveAttribute('aria-haspopup', 'menu');
    expect(trigger).toHaveAttribute('aria-expanded', 'false');
  });

  it('opens dropdown on click and shows all items', () => {
    const items = makeItems();
    render(<ToolbarOverflowMenu items={items} />);

    fireEvent.click(screen.getByTitle('More toolbar actions'));

    expect(screen.getByTitle('More toolbar actions')).toHaveAttribute('aria-expanded', 'true');
    expect(screen.getByRole('menu')).toBeInTheDocument();
    expect(screen.getByText('Search Elements')).toBeInTheDocument();
    expect(screen.getByText('Model Settings')).toBeInTheDocument();
  });

  it('calls onClick and closes menu when an item is clicked', () => {
    const onClick = jest.fn();
    const items = makeItems([{ id: 'search', icon: <FiSearch />, label: 'Search', onClick }]);
    render(<ToolbarOverflowMenu items={items} />);

    fireEvent.click(screen.getByTitle('More toolbar actions'));
    fireEvent.click(screen.getByText('Search'));

    expect(onClick).toHaveBeenCalledTimes(1);
    // Menu should be closed
    expect(screen.queryByRole('menu')).not.toBeInTheDocument();
  });

  it('does not call onClick for disabled items', () => {
    const onClick = jest.fn();
    const items = makeItems([
      { id: 'search', icon: <FiSearch />, label: 'Search', onClick, disabled: true },
    ]);
    render(<ToolbarOverflowMenu items={items} />);

    fireEvent.click(screen.getByTitle('More toolbar actions'));
    fireEvent.click(screen.getByText('Search'));

    expect(onClick).not.toHaveBeenCalled();
  });

  it('adds active class to active items', () => {
    const items = makeItems([
      { id: 'search', icon: <FiSearch />, label: 'Search', onClick: jest.fn(), active: true },
    ]);
    render(<ToolbarOverflowMenu items={items} />);

    fireEvent.click(screen.getByTitle('More toolbar actions'));

    const menuItem = screen.getByText('Search').closest('.toolbar-overflow-item');
    expect(menuItem).toHaveClass('active');
  });

  it('adds disabled class to disabled items', () => {
    const items = makeItems([
      { id: 'search', icon: <FiSearch />, label: 'Search', onClick: jest.fn(), disabled: true },
    ]);
    render(<ToolbarOverflowMenu items={items} />);

    fireEvent.click(screen.getByTitle('More toolbar actions'));

    const menuItem = screen.getByText('Search').closest('.toolbar-overflow-item');
    expect(menuItem).toHaveClass('disabled');
    expect(menuItem).toHaveAttribute('aria-disabled', 'true');
  });

  it('closes menu on Escape key', () => {
    render(<ToolbarOverflowMenu items={makeItems()} />);

    fireEvent.click(screen.getByTitle('More toolbar actions'));
    expect(screen.getByRole('menu')).toBeInTheDocument();

    fireEvent.keyDown(screen.getByText('Search Elements'), { key: 'Escape' });
    expect(screen.queryByRole('menu')).not.toBeInTheDocument();
  });

  it('triggers item on Enter key', () => {
    const onClick = jest.fn();
    const items = makeItems([{ id: 'search', icon: <FiSearch />, label: 'Search', onClick }]);
    render(<ToolbarOverflowMenu items={items} />);

    fireEvent.click(screen.getByTitle('More toolbar actions'));
    fireEvent.keyDown(screen.getByText('Search'), { key: 'Enter' });

    expect(onClick).toHaveBeenCalledTimes(1);
  });

  it('triggers item on Space key', () => {
    const onClick = jest.fn();
    const items = makeItems([{ id: 'search', icon: <FiSearch />, label: 'Search', onClick }]);
    render(<ToolbarOverflowMenu items={items} />);

    fireEvent.click(screen.getByTitle('More toolbar actions'));
    fireEvent.keyDown(screen.getByText('Search'), { key: ' ' });

    expect(onClick).toHaveBeenCalledTimes(1);
  });

  it('toggles menu open/closed on repeated clicks', () => {
    render(<ToolbarOverflowMenu items={makeItems()} />);

    const trigger = screen.getByTitle('More toolbar actions');

    fireEvent.click(trigger);
    expect(screen.getByRole('menu')).toBeInTheDocument();

    fireEvent.click(trigger);
    expect(screen.queryByRole('menu')).not.toBeInTheDocument();
  });
});
