import { describe, it, expect, vi } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { DraggableEvent } from '../DraggableEvent';

// Mock DnD Kit
vi.mock('@dnd-kit/core', () => ({
  DndContext: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
  useDraggable: vi.fn(() => ({
    attributes: {},
    listeners: {},
    setNodeRef: vi.fn(),
    transform: null,
    isDragging: false,
  })),
}));

vi.mock('@dnd-kit/utilities', () => ({
  CSS: {
    Translate: {
      toString: (transform: any) => transform ? `translate3d(${transform.x}px, ${transform.y}px, 0)` : undefined,
    },
  },
}));

describe('DraggableEvent', () => {
  const defaultProps = {
    id: 1,
    title: 'Test Event',
    serviceName: 'Test Service',
    status: 'CONFIRMED' as const,
    isPaid: false,
    start: new Date('2024-01-01T10:00:00'),
    end: new Date('2024-01-01T11:00:00'),
    laneIndex: 0,
    height: 80,
    left: 100,
    width: 200,
    top: 10,
    onResizeStart: vi.fn(),
  };

  it('renders the event title', () => {
    render(<DraggableEvent {...defaultProps} />);
    expect(screen.getByText('Test Event')).toBeInTheDocument();
  });

  it('renders the service name when provided', () => {
    render(<DraggableEvent {...defaultProps} />);
    expect(screen.getByText('Test Service')).toBeInTheDocument();
  });

  it('does not render service name when not provided', () => {
    render(<DraggableEvent {...defaultProps} serviceName={undefined} />);
    expect(screen.queryByText('Test Service')).not.toBeInTheDocument();
  });

  it('displays the start time formatted correctly', () => {
    render(<DraggableEvent {...defaultProps} />);
    expect(screen.getByText('10:00 AM')).toBeInTheDocument();
  });

  it('applies correct position styles', () => {
    const { container } = render(<DraggableEvent {...defaultProps} />);
    const eventElement = container.querySelector('.absolute.rounded-b');

    expect(eventElement).toHaveStyle({
      left: '100px',
      width: '200px',
      top: '10px',
      height: '80px',
    });
  });

  it('applies confirmed status border color', () => {
    const { container } = render(
      <DraggableEvent {...defaultProps} status="CONFIRMED" />
    );
    const eventElement = container.querySelector('.absolute.rounded-b');
    expect(eventElement).toHaveClass('border-blue-500');
  });

  it('applies completed status border color', () => {
    const { container } = render(
      <DraggableEvent {...defaultProps} status="COMPLETED" />
    );
    const eventElement = container.querySelector('.absolute.rounded-b');
    expect(eventElement).toHaveClass('border-green-500');
  });

  it('applies cancelled status border color', () => {
    const { container } = render(
      <DraggableEvent {...defaultProps} status="CANCELLED" />
    );
    const eventElement = container.querySelector('.absolute.rounded-b');
    expect(eventElement).toHaveClass('border-red-500');
  });

  it('applies no-show status border color', () => {
    const { container } = render(
      <DraggableEvent {...defaultProps} status="NO_SHOW" />
    );
    const eventElement = container.querySelector('.absolute.rounded-b');
    expect(eventElement).toHaveClass('border-gray-500');
  });

  it('applies green border when paid', () => {
    const { container } = render(
      <DraggableEvent {...defaultProps} isPaid={true} />
    );
    const eventElement = container.querySelector('.absolute.rounded-b');
    expect(eventElement).toHaveClass('border-green-500');
  });

  it('applies default brand border color for scheduled status', () => {
    const { container } = render(
      <DraggableEvent {...defaultProps} status="SCHEDULED" />
    );
    const eventElement = container.querySelector('.absolute.rounded-b');
    expect(eventElement).toHaveClass('border-brand-500');
  });

  it('calls onResizeStart when top resize handle is clicked', () => {
    const onResizeStart = vi.fn();
    const { container } = render(
      <DraggableEvent {...defaultProps} onResizeStart={onResizeStart} />
    );

    const topHandle = container.querySelector('.cursor-ns-resize');
    if (topHandle) {
      fireEvent.mouseDown(topHandle);
      expect(onResizeStart).toHaveBeenCalledWith(
        expect.any(Object),
        'left',
        1
      );
    }
  });

  it('calls onResizeStart when bottom resize handle is clicked', () => {
    const onResizeStart = vi.fn();
    const { container } = render(
      <DraggableEvent {...defaultProps} onResizeStart={onResizeStart} />
    );

    const handles = container.querySelectorAll('.cursor-ns-resize');
    const bottomHandle = handles[handles.length - 1]; // Get the last one (bottom)

    if (bottomHandle) {
      fireEvent.mouseDown(bottomHandle);
      expect(onResizeStart).toHaveBeenCalledWith(
        expect.any(Object),
        'right',
        1
      );
    }
  });

  it('renders grip icon', () => {
    const { container } = render(<DraggableEvent {...defaultProps} />);
    const gripIcon = container.querySelector('svg');
    expect(gripIcon).toBeInTheDocument();
  });

  it('applies hover styles', () => {
    const { container } = render(<DraggableEvent {...defaultProps} />);
    const eventElement = container.querySelector('.absolute.rounded-b');
    expect(eventElement).toHaveClass('group', 'hover:shadow-md');
  });

  it('renders with correct base styling classes', () => {
    const { container } = render(<DraggableEvent {...defaultProps} />);
    const eventElement = container.querySelector('.absolute.rounded-b');
    expect(eventElement).toHaveClass(
      'absolute',
      'rounded-b',
      'overflow-hidden',
      'group',
      'bg-brand-100'
    );
  });

  it('has two resize handles', () => {
    const { container } = render(<DraggableEvent {...defaultProps} />);
    const handles = container.querySelectorAll('.cursor-ns-resize');
    expect(handles).toHaveLength(2);
  });

  it('stops propagation when resize handle is clicked', () => {
    const onResizeStart = vi.fn();
    const { container } = render(
      <DraggableEvent {...defaultProps} onResizeStart={onResizeStart} />
    );

    const topHandle = container.querySelector('.cursor-ns-resize');
    const mockEvent = {
      stopPropagation: vi.fn(),
    } as any;

    if (topHandle) {
      fireEvent.mouseDown(topHandle, mockEvent);
      // The event handler should call stopPropagation to prevent drag
      expect(onResizeStart).toHaveBeenCalled();
    }
  });

  it('renders content area with cursor-move', () => {
    const { container } = render(<DraggableEvent {...defaultProps} />);
    const contentArea = container.querySelector('.cursor-move');
    expect(contentArea).toBeInTheDocument();
    expect(contentArea).toHaveClass('select-none');
  });

  it('applies different heights correctly', () => {
    const { container } = render(
      <DraggableEvent {...defaultProps} height={100} />
    );
    const eventElement = container.querySelector('.absolute.rounded-b');
    expect(eventElement).toHaveStyle({ height: '100px' });
  });

  it('applies different widths correctly', () => {
    const { container } = render(
      <DraggableEvent {...defaultProps} width={300} />
    );
    const eventElement = container.querySelector('.absolute.rounded-b');
    expect(eventElement).toHaveStyle({ width: '300px' });
  });
});
