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

// 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('StartNode', () => {
  const defaultProps = {
    id: 'start-1',
    data: {
      label: 'Test Event',
    },
    selected: false,
    type: 'start',
    xPos: 0,
    yPos: 0,
    isConnectable: true,
    zIndex: 0,
    dragging: false,
    targetPosition: undefined,
    sourcePosition: undefined,
  };

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

    it('should render default label when no label provided', () => {
      render(<StartNode {...defaultProps} data={{}} />);
      expect(screen.getByText('Start', { selector: '.node-label' })).toBeInTheDocument();
    });

    it('should render type indicator as Start', () => {
      render(<StartNode {...defaultProps} />);
      expect(screen.getByText('Start', { selector: '.node-type' })).toBeInTheDocument();
    });

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

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

    it('should render plugin name when provided', () => {
      render(
        <StartNode
          {...defaultProps}
          data={{ label: 'Test', plugin: 'content_entity:insert' }}
        />
      );
      expect(screen.getByText('content_entity:insert')).toBeInTheDocument();
    });

    it('should not render plugin div when not provided', () => {
      const { container } = render(
        <StartNode {...defaultProps} data={{ label: 'Test' }} />
      );
      expect(container.querySelector('.node-plugin')).not.toBeInTheDocument();
    });
  });

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

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

    it('should not show selected class when locked even if selected', () => {
      const { container } = render(
        <StartNode
          {...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(
        <StartNode
          {...defaultProps}
          data={{ label: 'Test', locked: true }}
        />
      );
      expect(container.querySelector('.lock-icon')).toBeInTheDocument();
    });

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

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

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

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

    it('should call onDelete when delete button clicked', () => {
      const onDelete = jest.fn();
      render(
        <StartNode
          {...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}>
          <StartNode
            {...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(
        <StartNode
          {...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(
        <StartNode
          {...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(
        <StartNode
          {...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(
        <StartNode
          {...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}>
          <StartNode
            {...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(
        <StartNode
          {...defaultProps}
          data={{ label: 'Test', annotation: 'Note' }}
        />
      );
      expect(container.firstChild).toHaveClass('node-has-annotation');
    });
  });
});
