import React from 'react';
import { describe, it, expect, vi } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { MonthView } from '@/components/calendar/MonthView';
import type { CalendarEntry } from '@/api/calendar';

const sampleEntries: CalendarEntry[] = [
  {
    id: 'a-1',
    calendar_id: 'cal-1',
    entry_type: 'appointment',
    subtype: 'normal',
    title: 'Team-Meeting',
    start_at: '2026-06-15T09:00:00.000Z',
    end_at: '2026-06-15T10:00:00.000Z',
    all_day: false,
    priority: 'medium',
    status: 'open',
    created_by: 'u-1',
  },
  {
    id: 'a-2',
    calendar_id: 'cal-1',
    entry_type: 'appointment',
    subtype: 'normal',
    title: 'Kundentermin',
    start_at: '2026-06-22T14:00:00.000Z',
    end_at: '2026-06-22T15:00:00.000Z',
    all_day: false,
    priority: 'high',
    status: 'open',
    created_by: 'u-1',
  },
];

describe('MonthView', () => {
  it('renders the month grid with header', () => {
    render(
      <MonthView
        visibleMonth={new Date(2026, 5, 1)}
        entries={[]}
        onCreateAt={vi.fn()}
        onEditEntry={vi.fn()}
        onMoveEntry={vi.fn()}
      />
    );
    expect(screen.getByTestId('month-view')).toBeInTheDocument();
    expect(screen.getByTestId('month-view-grid')).toBeInTheDocument();
    // Header includes month name and year
    expect(screen.getByTestId('month-view-header').textContent).toContain('2026');
  });

  it('renders all 42 day cells (6 weeks × 7 days)', () => {
    render(
      <MonthView
        visibleMonth={new Date(2026, 5, 1)}
        entries={[]}
        onCreateAt={vi.fn()}
        onEditEntry={vi.fn()}
        onMoveEntry={vi.fn()}
      />
    );
    const cells = screen.getAllByRole('button', { hidden: false }).filter((el) =>
      el.getAttribute('data-testid')?.startsWith('month-cell-')
    );
    expect(cells.length).toBe(42);
  });

  it('renders an entry chip for each appointment and clicking it fires onEditEntry', () => {
    const onEdit = vi.fn();
    render(
      <MonthView
        visibleMonth={new Date(2026, 5, 1)}
        entries={sampleEntries}
        onCreateAt={vi.fn()}
        onEditEntry={onEdit}
        onMoveEntry={vi.fn()}
      />
    );
    expect(screen.getByTestId('month-entry-a-1')).toBeInTheDocument();
    expect(screen.getByTestId('month-entry-a-2')).toBeInTheDocument();
    fireEvent.click(screen.getByTestId('month-entry-a-1'));
    expect(onEdit).toHaveBeenCalledWith(
      expect.objectContaining({ id: 'a-1', title: 'Team-Meeting' })
    );
  });

  it('clicking an empty cell fires onCreateAt with the day Date', () => {
    const onCreate = vi.fn();
    render(
      <MonthView
        visibleMonth={new Date(2026, 5, 1)}
        entries={[]}
        onCreateAt={onCreate}
        onEditEntry={vi.fn()}
        onMoveEntry={vi.fn()}
      />
    );
    // Pick the first cell of the grid
    const cells = screen.getAllByRole('button', { hidden: false }).filter((el) =>
      el.getAttribute('data-testid')?.startsWith('month-cell-')
    );
    fireEvent.click(cells[0]);
    expect(onCreate).toHaveBeenCalledTimes(1);
    const arg = onCreate.mock.calls[0][0] as Date;
    expect(arg).toBeInstanceOf(Date);
  });

  it('drag-and-drop fires onMoveEntry with the new start time-of-day preserved', () => {
    const onMove = vi.fn();
    const { container } = render(
      <MonthView
        visibleMonth={new Date(2026, 5, 1)}
        entries={sampleEntries}
        onCreateAt={vi.fn()}
        onEditEntry={vi.fn()}
        onMoveEntry={onMove}
      />
    );
    const entryEl = screen.getByTestId('month-entry-a-1');
    const cells = container.querySelectorAll('[data-testid^="month-cell-"]');
    // Pick a cell that's clearly different from June 15
    const targetCell = cells[20] as HTMLElement;
    const dataTransfer = {
      setData: vi.fn(),
      getData: (k: string) => (k === 'application/x-calendar-entry' ? 'a-1' : ''),
      types: ['application/x-calendar-entry'],
      effectAllowed: '',
      dropEffect: '',
    };
    fireEvent.dragStart(entryEl, { dataTransfer });
    fireEvent.dragOver(targetCell, { dataTransfer });
    fireEvent.drop(targetCell, { dataTransfer });
    expect(onMove).toHaveBeenCalledTimes(1);
    const [, newStart] = onMove.mock.calls[0];
    expect(newStart).toBeInstanceOf(Date);
  });
});
