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

// Mock ReactFlow components
jest.mock('reactflow', () => ({
  Handle: ({ type, position, id }: any) => (
    <div data-testid={`handle-${type}-${id}`} data-position={position} />
  ),
  Position: {
    Top: 'top',
    Bottom: 'bottom',
    Left: 'left',
    Right: 'right',
  },
}));

describe('GatewayNode', () => {
  const defaultProps = {
    id: 'gateway-1',
    data: {
      label: 'Test Gateway',
    },
    selected: false,
    type: 'gateway',
    xPos: 0,
    yPos: 0,
    isConnectable: true,
    zIndex: 0,
    dragging: false,
    targetPosition: undefined,
    sourcePosition: undefined,
  };

  describe('rendering', () => {
    it('should render gateway node with label', () => {
      render(<GatewayNode {...defaultProps} />);
      expect(screen.getByText('Test Gateway')).toBeInTheDocument();
    });

    it('should render default label when no label provided', () => {
      render(<GatewayNode {...defaultProps} data={{}} />);
      expect(screen.getByText('Gateway')).toBeInTheDocument();
    });

    it('should render input handle at top', () => {
      render(<GatewayNode {...defaultProps} />);
      const handle = screen.getByTestId('handle-target-input');
      expect(handle).toBeInTheDocument();
      expect(handle).toHaveAttribute('data-position', 'top');
    });

    it('should render true output handle on the right', () => {
      render(<GatewayNode {...defaultProps} />);
      const handle = screen.getByTestId('handle-source-true');
      expect(handle).toBeInTheDocument();
      expect(handle).toHaveAttribute('data-position', 'right');
    });

    it('should render false output handle at bottom', () => {
      render(<GatewayNode {...defaultProps} />);
      const handle = screen.getByTestId('handle-source-false');
      expect(handle).toBeInTheDocument();
      expect(handle).toHaveAttribute('data-position', 'bottom');
    });

    it('should have gateway-node class', () => {
      const { container } = render(<GatewayNode {...defaultProps} />);
      expect(container.firstChild).toHaveClass('gateway-node');
    });

    it('should render diamond shape container', () => {
      const { container } = render(<GatewayNode {...defaultProps} />);
      expect(container.querySelector('.gateway-diamond')).toBeInTheDocument();
    });
  });

  describe('selected state', () => {
    it('should have selected class when selected', () => {
      const { container } = render(
        <GatewayNode {...defaultProps} selected={true} />
      );
      expect(container.firstChild).toHaveClass('selected');
    });

    it('should not have selected class when not selected', () => {
      const { container } = render(
        <GatewayNode {...defaultProps} selected={false} />
      );
      expect(container.firstChild).not.toHaveClass('selected');
    });

    it('should not show selected class when locked even if selected', () => {
      const { container } = render(
        <GatewayNode
          {...defaultProps}
          selected={true}
          data={{ label: 'Test', locked: true }}
        />
      );
      expect(container.firstChild).not.toHaveClass('selected');
    });
  });

  describe('locked state', () => {
    it('should show lock icon when locked', () => {
      const { container } = render(
        <GatewayNode
          {...defaultProps}
          data={{ label: 'Test', locked: true }}
        />
      );
      expect(container.querySelector('.lock-icon-rotated')).toBeInTheDocument();
    });

    it('should not show delete button when locked', () => {
      render(
        <GatewayNode
          {...defaultProps}
          data={{ label: 'Test', locked: true }}
        />
      );
      expect(screen.queryByTitle('Delete node')).not.toBeInTheDocument();
    });

    it('should not show delete button when isLocked is true', () => {
      render(
        <GatewayNode
          {...defaultProps}
          data={{ label: 'Test', isLocked: true }}
        />
      );
      expect(screen.queryByTitle('Delete node')).not.toBeInTheDocument();
    });

    it('should have locked class when locked', () => {
      const { container } = render(
        <GatewayNode
          {...defaultProps}
          data={{ label: 'Test', locked: true }}
        />
      );
      expect(container.firstChild).toHaveClass('node-locked');
    });
  });

  describe('delete functionality', () => {
    it('should show delete button when not locked', () => {
      render(
        <GatewayNode
          {...defaultProps}
          data={{ label: 'Test' }}
        />
      );
      expect(screen.getByTitle('Delete node')).toBeInTheDocument();
    });

    it('should call onDelete when delete button clicked', () => {
      const onDelete = jest.fn();
      render(
        <GatewayNode
          {...defaultProps}
          data={{ label: 'Test', onDelete }}
        />
      );
      fireEvent.click(screen.getByTitle('Delete node'));
      expect(onDelete).toHaveBeenCalled();
    });

    it('should stop propagation on delete click', () => {
      const onDelete = jest.fn();
      const onContainerClick = jest.fn();

      render(
        <div onClick={onContainerClick}>
          <GatewayNode
            {...defaultProps}
            data={{ label: 'Test', onDelete }}
          />
        </div>
      );

      fireEvent.click(screen.getByTitle('Delete node'));
      expect(onDelete).toHaveBeenCalled();
      expect(onContainerClick).not.toHaveBeenCalled();
    });

    it('should not throw when onDelete is not provided', () => {
      render(
        <GatewayNode
          {...defaultProps}
          data={{ label: 'Test' }}
        />
      );
      expect(() => {
        fireEvent.click(screen.getByTitle('Delete node'));
      }).not.toThrow();
    });
  });

  describe('annotation', () => {
    it('should show annotation icon when annotation exists', () => {
      const { container } = render(
        <GatewayNode
          {...defaultProps}
          data={{ label: 'Test', annotation: 'Test annotation' }}
        />
      );
      expect(container.querySelector('.annotation-icon')).toBeInTheDocument();
    });

    it('should have active class on annotation icon when visible', () => {
      const { container } = render(
        <GatewayNode
          {...defaultProps}
          data={{
            label: 'Test',
            annotation: 'Note',
            isAnnotationVisible: true,
          }}
        />
      );
      expect(container.querySelector('.annotation-icon')).toHaveClass('active');
    });

    it('should call onToggleAnnotation when annotation icon clicked', () => {
      const onToggle = jest.fn();
      const { container } = render(
        <GatewayNode
          {...defaultProps}
          data={{
            label: 'Test',
            annotation: 'Note',
            onToggleAnnotation: onToggle,
          }}
        />
      );

      fireEvent.click(container.querySelector('.annotation-icon')!);
      expect(onToggle).toHaveBeenCalled();
    });

    it('should stop propagation on annotation icon click', () => {
      const onToggle = jest.fn();
      const onContainerClick = jest.fn();

      const { container } = render(
        <div onClick={onContainerClick}>
          <GatewayNode
            {...defaultProps}
            data={{
              label: 'Test',
              annotation: 'Note',
              onToggleAnnotation: onToggle,
            }}
          />
        </div>
      );

      fireEvent.click(container.querySelector('.annotation-icon')!);
      expect(onContainerClick).not.toHaveBeenCalled();
    });

    it('should have has-annotation class when annotation exists', () => {
      const { container } = render(
        <GatewayNode
          {...defaultProps}
          data={{ label: 'Test', annotation: 'Note' }}
        />
      );
      expect(container.firstChild).toHaveClass('node-has-annotation');
    });
  });

  describe('diamond sizing', () => {
    it('should render diamond with initial size', () => {
      const { container } = render(<GatewayNode {...defaultProps} />);
      const diamond = container.querySelector('.gateway-diamond');
      expect(diamond).toHaveStyle({ width: '56px', height: '56px' });
    });
  });
});
