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

vi.mock('@/api/calendar', async () => {
  const actual = await vi.importActual<typeof import('@/api/calendar')>('@/api/calendar');
  return {
    ...actual,
    createEntry: vi.fn(),
    updateEntry: vi.fn(),
    deleteEntry: vi.fn(),
  };
});

import { createEntry, updateEntry, deleteEntry } from '@/api/calendar';

const calendars: Calendar[] = [
  {
    id: 'cal-1',
    name: 'Persönlich',
    color: '#3B82F6',
    type: 'personal',
    owner_id: 'u-1',
  },
];

const sampleEntry: CalendarEntry = {
  id: 'e-1',
  calendar_id: 'cal-1',
  entry_type: 'appointment',
  subtype: 'normal',
  title: 'Bestehender Termin',
  description: 'Notiz',
  location: 'Berlin',
  start_at: '2026-06-20T09:00:00.000Z',
  end_at: '2026-06-20T10:00:00.000Z',
  all_day: false,
  priority: 'medium',
  status: 'open',
  created_by: 'u-1',
};

describe('AppointmentModal', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('renders the create modal with pre-filled date from prefillDate', () => {
    render(
      <AppointmentModal
        open
        onClose={vi.fn()}
        prefillDate={new Date(2026, 6, 1)}
        calendars={calendars}
        defaultCalendarId="cal-1"
        onSaved={vi.fn()}
        onDeleted={vi.fn()}
      />
    );
    expect(screen.getByTestId('appointment-modal')).toBeInTheDocument();
    const start = screen.getByTestId('appointment-start') as HTMLInputElement;
    expect(start.value).toMatch(/2026-07-01/);
  });

  it('in edit mode, prefills the form with the entry fields and shows the delete button', () => {
    render(
      <AppointmentModal
        open
        onClose={vi.fn()}
        entry={sampleEntry}
        calendars={calendars}
        defaultCalendarId="cal-1"
        onSaved={vi.fn()}
        onDeleted={vi.fn()}
      />
    );
    expect((screen.getByTestId('appointment-title') as HTMLInputElement).value).toBe(
      'Bestehender Termin'
    );
    expect(screen.getByTestId('appointment-delete')).toBeInTheDocument();
  });

  it('save in create mode calls createEntry and onSaved', async () => {
    (createEntry as unknown as ReturnType<typeof vi.fn>).mockResolvedValue(sampleEntry);
    const onSaved = vi.fn();
    const onClose = vi.fn();
    render(
      <AppointmentModal
        open
        onClose={onClose}
        prefillDate={new Date(2026, 6, 1, 9, 0)}
        calendars={calendars}
        defaultCalendarId="cal-1"
        onSaved={onSaved}
        onDeleted={vi.fn()}
      />
    );
    fireEvent.change(screen.getByTestId('appointment-title'), {
      target: { value: 'Neuer Termin' },
    });
    fireEvent.click(screen.getByTestId('appointment-save'));
    await waitFor(() => {
      expect(createEntry).toHaveBeenCalledTimes(1);
    });
    expect(onSaved).toHaveBeenCalledWith(sampleEntry);
    expect(onClose).toHaveBeenCalled();
  });

  it('save in edit mode calls updateEntry and onSaved', async () => {
    (updateEntry as unknown as ReturnType<typeof vi.fn>).mockResolvedValue({
      ...sampleEntry,
      title: 'Geändert',
    });
    const onSaved = vi.fn();
    render(
      <AppointmentModal
        open
        onClose={vi.fn()}
        entry={sampleEntry}
        calendars={calendars}
        defaultCalendarId="cal-1"
        onSaved={onSaved}
        onDeleted={vi.fn()}
      />
    );
    fireEvent.change(screen.getByTestId('appointment-title'), {
      target: { value: 'Geändert' },
    });
    fireEvent.click(screen.getByTestId('appointment-save'));
    await waitFor(() => {
      expect(updateEntry).toHaveBeenCalledWith(
        'e-1',
        expect.objectContaining({ title: 'Geändert' })
      );
    });
    expect(onSaved).toHaveBeenCalled();
  });

  it('shows a validation error when title is empty', async () => {
    render(
      <AppointmentModal
        open
        onClose={vi.fn()}
        prefillDate={new Date(2026, 6, 1)}
        calendars={calendars}
        defaultCalendarId="cal-1"
        onSaved={vi.fn()}
        onDeleted={vi.fn()}
      />
    );
    fireEvent.click(screen.getByTestId('appointment-save'));
    const err = await screen.findByTestId('appointment-error');
    expect(err.textContent?.toLowerCase()).toContain('erforderlich');
  });

  it('delete button calls deleteEntry and onDeleted', async () => {
    (deleteEntry as unknown as ReturnType<typeof vi.fn>).mockResolvedValue(undefined);
    const onDeleted = vi.fn();
    const onClose = vi.fn();
    // Stub confirm
    window.confirm = vi.fn(() => true);
    render(
      <AppointmentModal
        open
        onClose={onClose}
        entry={sampleEntry}
        calendars={calendars}
        defaultCalendarId="cal-1"
        onSaved={vi.fn()}
        onDeleted={onDeleted}
      />
    );
    fireEvent.click(screen.getByTestId('appointment-delete'));
    await waitFor(() => {
      expect(deleteEntry).toHaveBeenCalledWith('e-1');
    });
    expect(onDeleted).toHaveBeenCalledWith('e-1');
    expect(onClose).toHaveBeenCalled();
  });
});
