import { render, screen, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
import { Ladder } from './Ladder';
import { Program, RungElement } from '../../engine/types';

describe('Ladder Component', () => {
  const mockOnElementClick = vi.fn();
  const mockOnDropElement = vi.fn();
  const mockOnMoveElement = vi.fn();

  const mockProgram: Program = {
    name: 'Test Program',
    cycleTime: 100,
    rungs: [
      {
        id: 'rung-1',
        enabled: true,
        series: [
          {
            type: 'contact',
            contactType: 'NO',
            address: 'I:0.0',
          } as RungElement,
          {
            type: 'coil',
            coilType: 'OUTPUT',
            address: 'Q:0.0',
          } as RungElement,
        ],
      },
    ],
  };

  const mockEngineState: any = {
    inputs: new Map([['I:0.0', { address: 'I:0.0', value: true }]]),
    outputs: new Map(),
  };

  it('renders the correct number of rungs', () => {
    render(
      <Ladder
        program={mockProgram}
        engineState={mockEngineState}
        onElementClick={mockOnElementClick}
        onDropElement={mockOnDropElement}
        onMoveElement={mockOnMoveElement}
      />
    );
    expect(screen.getByText('1')).toBeInTheDocument();
  });

  it('calls onElementClick when an element is clicked', () => {
    render(
      <Ladder
        program={mockProgram}
        engineState={mockEngineState}
        onElementClick={mockOnElementClick}
        onDropElement={mockOnDropElement}
        onMoveElement={mockOnMoveElement}
      />
    );

    // Click on the element text
    const elementText = screen.getByText('I:0.0');
    fireEvent.click(elementText);

    expect(mockOnElementClick).toHaveBeenCalledWith(0, 0, mockProgram.rungs[0].series[0]);
  });

  it('calls onDropElement when an element is dropped on a rung', () => {
    render(
      <Ladder
        program={mockProgram}
        engineState={mockEngineState}
        onElementClick={mockOnElementClick}
        onDropElement={mockOnDropElement}
        onMoveElement={mockOnMoveElement}
      />
    );

    // The drop zone is a transparent rect inside the rung group
    const svg = document.querySelector('svg');
    const dropRect = svg?.querySelector('rect[fill="transparent"]');
    if (!dropRect) throw new Error('Drop zone rect not found');

    fireEvent.drop(dropRect, {
      dataTransfer: {
        getData: (type: string) => type === 'text/plain' ? 'contact-no' : '',
      } as any,
    });

    expect(mockOnDropElement).toHaveBeenCalledWith('contact-no', 0);
  });
});