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

// Mock react-icons
jest.mock('react-icons/fi', () => ({
  FiActivity: () => <span data-testid="fi-activity" />,
  FiZap: () => <span data-testid="fi-zap" />,
  FiGitBranch: () => <span data-testid="fi-git-branch" />,
  FiBox: () => <span data-testid="fi-box" />,
  FiLock: () => <span data-testid="fi-lock" />,
  FiUnlock: () => <span data-testid="fi-unlock" />,
  FiTrash2: () => <span data-testid="fi-trash2" />,
}));

describe('MultiSelectionPanel', () => {
  const mockOnConfigurationChange = jest.fn();
  const mockOnEdgeConfigurationChange = jest.fn();

  const defaultProps = {
    selectedNodes: [],
    selectedEdges: [],
    onConfigurationChange: mockOnConfigurationChange,
    onEdgeConfigurationChange: mockOnEdgeConfigurationChange,
    isLocked: false,
  };

  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('node list', () => {
    it('should render selected nodes with labels', () => {
      const nodes = [
        { id: 'node-1', type: 'start', data: { label: 'Event A' }, position: { x: 0, y: 0 } },
        { id: 'node-2', type: 'element', data: { label: 'Action B' }, position: { x: 100, y: 0 } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedNodes={nodes as any} />);
      
      expect(screen.getByText('Event A')).toBeTruthy();
      expect(screen.getByText('Action B')).toBeTruthy();
    });

    it('should show node count in header', () => {
      const nodes = [
        { id: 'node-1', type: 'start', data: { label: 'A' }, position: { x: 0, y: 0 } },
        { id: 'node-2', type: 'start', data: { label: 'B' }, position: { x: 0, y: 0 } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedNodes={nodes as any} />);
      expect(screen.getByText('Components (2)')).toBeTruthy();
    });

    it('should show "Unnamed" for nodes without labels', () => {
      const nodes = [
        { id: 'node-1', type: 'element', data: {}, position: { x: 0, y: 0 } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedNodes={nodes as any} />);
      expect(screen.getByText('Unnamed')).toBeTruthy();
    });
  });

  describe('edge list', () => {
    it('should render selected edges', () => {
      const edges = [
        { id: 'edge-1', source: 'a', target: 'b', data: { conditionLabel: 'Condition X' } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedEdges={edges as any} />);
      expect(screen.getByText('Condition X')).toBeTruthy();
    });

    it('should show edge count in header', () => {
      const edges = [
        { id: 'edge-1', source: 'a', target: 'b', data: {} },
        { id: 'edge-2', source: 'b', target: 'c', data: {} },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedEdges={edges as any} />);
      expect(screen.getByText('Connections (2)')).toBeTruthy();
    });

    it('should show "No condition" for edges without labels', () => {
      const edges = [
        { id: 'edge-1', source: 'a', target: 'b', data: {} },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedEdges={edges as any} />);
      expect(screen.getByText('No condition')).toBeTruthy();
    });
  });

  describe('lock/unlock actions', () => {
    it('should call onConfigurationChange when locking a node', () => {
      const nodes = [
        { id: 'node-1', type: 'element', data: { label: 'A', locked: false }, position: { x: 0, y: 0 } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedNodes={nodes as any} />);
      
      // Click the individual lock button
      const lockButtons = screen.getAllByTitle('Lock');
      fireEvent.click(lockButtons[0]);
      
      expect(mockOnConfigurationChange).toHaveBeenCalledWith('node-1', {
        _componentLocked: true,
      });
    });

    it('should disable lock buttons when globally locked', () => {
      const nodes = [
        { id: 'node-1', type: 'element', data: { label: 'A' }, position: { x: 0, y: 0 } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedNodes={nodes as any} isLocked={true} />);
      
      const lockButtons = screen.getAllByTitle('Lock');
      expect(lockButtons[0]).toBeDisabled();
    });

    it('should lock all selected items when Lock All is clicked', () => {
      const nodes = [
        { id: 'node-1', type: 'element', data: { label: 'A', locked: false }, position: { x: 0, y: 0 } },
        { id: 'node-2', type: 'element', data: { label: 'B', locked: false }, position: { x: 100, y: 0 } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedNodes={nodes as any} />);
      
      const lockAllBtn = screen.getByTitle('Lock all selected items');
      fireEvent.click(lockAllBtn);

      expect(mockOnConfigurationChange).toHaveBeenCalledTimes(2);
      expect(mockOnConfigurationChange).toHaveBeenCalledWith('node-1', { _componentLocked: true });
      expect(mockOnConfigurationChange).toHaveBeenCalledWith('node-2', { _componentLocked: true });
    });

    it('should unlock all selected items when Unlock All is clicked', () => {
      const nodes = [
        { id: 'node-1', type: 'element', data: { label: 'A', locked: true }, position: { x: 0, y: 0 } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedNodes={nodes as any} />);
      
      const unlockAllBtn = screen.getByTitle('Unlock all selected items');
      fireEvent.click(unlockAllBtn);

      expect(mockOnConfigurationChange).toHaveBeenCalledWith('node-1', { _componentLocked: false });
    });

    it('should disable Lock All when all items are already locked', () => {
      const nodes = [
        { id: 'node-1', type: 'element', data: { label: 'A', locked: true }, position: { x: 0, y: 0 } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedNodes={nodes as any} />);
      
      const lockAllBtn = screen.getByTitle('Lock all selected items');
      expect(lockAllBtn).toBeDisabled();
    });

    it('should disable Unlock All when no items are locked', () => {
      const nodes = [
        { id: 'node-1', type: 'element', data: { label: 'A', locked: false }, position: { x: 0, y: 0 } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedNodes={nodes as any} />);
      
      const unlockAllBtn = screen.getByTitle('Unlock all selected items');
      expect(unlockAllBtn).toBeDisabled();
    });
  });

  describe('summary note', () => {
    it('should show note about single selection', () => {
      render(<MultiSelectionPanel {...defaultProps} />);
      expect(screen.getByText('Select a single component or connection to view its configuration.')).toBeTruthy();
    });
  });

  describe('delete all action', () => {
    it('should render Delete All button', () => {
      const nodes = [
        { id: 'node-1', type: 'element', data: { label: 'A' }, position: { x: 0, y: 0 } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedNodes={nodes as any} />);

      expect(screen.getByTitle('Delete all selected items')).toBeTruthy();
      expect(screen.getByText('Delete All')).toBeTruthy();
    });

    it('should call onDeleteSelected when Delete All is clicked', () => {
      const mockOnDeleteSelected = jest.fn();
      const nodes = [
        { id: 'node-1', type: 'element', data: { label: 'A' }, position: { x: 0, y: 0 } },
      ];

      render(
        <MultiSelectionPanel
          {...defaultProps}
          selectedNodes={nodes as any}
          onDeleteSelected={mockOnDeleteSelected}
        />
      );

      const deleteAllBtn = screen.getByTitle('Delete all selected items');
      fireEvent.click(deleteAllBtn);

      expect(mockOnDeleteSelected).toHaveBeenCalled();
    });

    it('should disable Delete All button when globally locked', () => {
      const nodes = [
        { id: 'node-1', type: 'element', data: { label: 'A' }, position: { x: 0, y: 0 } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedNodes={nodes as any} isLocked={true} />);

      const deleteAllBtn = screen.getByTitle('Delete all selected items');
      expect(deleteAllBtn).toBeDisabled();
    });

    it('should not call onDeleteSelected when locked', () => {
      const mockOnDeleteSelected = jest.fn();
      const nodes = [
        { id: 'node-1', type: 'element', data: { label: 'A' }, position: { x: 0, y: 0 } },
      ];

      render(
        <MultiSelectionPanel
          {...defaultProps}
          selectedNodes={nodes as any}
          onDeleteSelected={mockOnDeleteSelected}
          isLocked={true}
        />
      );

      const deleteAllBtn = screen.getByTitle('Delete all selected items');
      expect(deleteAllBtn).toBeDisabled();
      fireEvent.click(deleteAllBtn);

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

    it('should not throw when onDeleteSelected is not provided', () => {
      const nodes = [
        { id: 'node-1', type: 'element', data: { label: 'A' }, position: { x: 0, y: 0 } },
      ];

      render(<MultiSelectionPanel {...defaultProps} selectedNodes={nodes as any} />);

      const deleteAllBtn = screen.getByTitle('Delete all selected items');
      expect(() => fireEvent.click(deleteAllBtn)).not.toThrow();
    });
  });
});
