/**
 * RED test scaffold: broker/write.ts — tsdav PUT/DELETE wrappers (CAL-04, CAL-05, CAL-06)
 *
 * Behaviors under test:
 *   1. createCalendarEvent calls client.createCalendarObject with `${uid}.ics` filename
 *   2. updateCalendarEvent passes etag into the calendarObject (If-Match for D-08)
 *   3. deleteCalendarEvent passes etag into the calendarObject (If-Match for D-08)
 *   4. Each returns the raw Response from the tsdav client mock
 *
 * These tests FAIL (RED) because broker/write.ts does not exist yet.
 * They will turn GREEN in Plan 03-02 when the implementation is added.
 */

import { describe, it, expect, vi } from 'vitest';

// This import fails (RED) — broker/write.ts does not exist yet.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore intentional RED import
import {
  createCalendarEvent,
  updateCalendarEvent,
  deleteCalendarEvent,
} from '../../src/broker/write.js';

const makeMockResponse = (status: number): Response =>
  ({ status, ok: status >= 200 && status < 300, headers: new Headers() }) as unknown as Response;

describe('createCalendarEvent', () => {
  it('calls client.createCalendarObject with uid.ics filename', async () => {
    const mockClient = {
      createCalendarObject: vi.fn().mockResolvedValue(makeMockResponse(201)),
    };
    const mockCalendar = {
      url: 'https://caldav.fastmail.com/dav/calendars/user/test@fm.com/Default/',
    };
    const uid = 'abc-123@familysync';
    const icsString = 'BEGIN:VCALENDAR\r\nEND:VCALENDAR';

    const result = await createCalendarEvent(
      mockClient as never,
      mockCalendar as never,
      uid,
      icsString,
    );

    expect(mockClient.createCalendarObject).toHaveBeenCalledWith({
      calendar: mockCalendar,
      filename: `${uid}.ics`,
      iCalString: icsString,
    });
    expect(result.status).toBe(201);
  });

  it('returns the raw Response from client', async () => {
    const mockClient = {
      createCalendarObject: vi.fn().mockResolvedValue(makeMockResponse(204)),
    };
    const mockCalendar = { url: 'https://caldav.fastmail.com/' };
    const result = await createCalendarEvent(
      mockClient as never,
      mockCalendar as never,
      'uid@fs',
      'ICS',
    );
    expect(result).toBeDefined();
    expect(result.status).toBe(204);
  });
});

describe('updateCalendarEvent', () => {
  it('calls client.updateCalendarObject with etag in calendarObject (If-Match)', async () => {
    const mockClient = {
      updateCalendarObject: vi.fn().mockResolvedValue(makeMockResponse(204)),
    };
    const calendarObjectUrl = 'https://caldav.fastmail.com/dav/calendars/user/test/Default/uid.ics';
    const icsString = 'BEGIN:VCALENDAR\r\nEND:VCALENDAR';
    const etag = '"etag-123"';

    const result = await updateCalendarEvent(
      mockClient as never,
      calendarObjectUrl,
      icsString,
      etag,
    );

    expect(mockClient.updateCalendarObject).toHaveBeenCalledWith({
      calendarObject: {
        url: calendarObjectUrl,
        data: icsString,
        etag,
      },
    });
    expect(result.status).toBe(204);
  });

  it('passes empty string as etag when etag is null (safe for If-Match)', async () => {
    const mockClient = {
      updateCalendarObject: vi.fn().mockResolvedValue(makeMockResponse(204)),
    };
    await updateCalendarEvent(
      mockClient as never,
      'https://caldav.fastmail.com/uid.ics',
      'ICS',
      null,
    );

    const callArg = mockClient.updateCalendarObject.mock.calls[0][0];
    expect(callArg.calendarObject.etag).toBe('');
  });
});

describe('deleteCalendarEvent', () => {
  it('calls client.deleteCalendarObject with etag in calendarObject (If-Match)', async () => {
    const mockClient = {
      deleteCalendarObject: vi.fn().mockResolvedValue(makeMockResponse(204)),
    };
    const calendarObjectUrl = 'https://caldav.fastmail.com/dav/calendars/user/test/Default/uid.ics';
    const etag = '"etag-456"';

    const result = await deleteCalendarEvent(mockClient as never, calendarObjectUrl, etag);

    expect(mockClient.deleteCalendarObject).toHaveBeenCalledWith({
      calendarObject: {
        url: calendarObjectUrl,
        data: '',
        etag,
      },
    });
    expect(result.status).toBe(204);
  });

  it('passes empty string as etag when etag is null', async () => {
    const mockClient = {
      deleteCalendarObject: vi.fn().mockResolvedValue(makeMockResponse(204)),
    };
    await deleteCalendarEvent(mockClient as never, 'https://caldav.fastmail.com/uid.ics', null);

    const callArg = mockClient.deleteCalendarObject.mock.calls[0][0];
    expect(callArg.calendarObject.etag).toBe('');
  });
});
