/**
 * DeleteConfirmationDialog tests — Task 3 (TDD RED → GREEN)
 *
 * Covers UI-SPEC §DeleteConfirmationDialog:
 *   - Renders heading "Delete event?" and body copy
 *   - Cancel button closes without deleting
 *   - Escape closes without deleting
 *   - Delete (red) button calls deleteEvent, sets lastSyncedUid, closes dialog and popover
 *   - Focus trapped inside dialog
 *   - T-03-17: mandatory two-tap confirmation (no single-tap delete)
 *   - T-03-18: failed delete toast persists (wired via lastSyncedUid → SyncStateToast)
 */

import 'temporal-polyfill/global';
import React from 'react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

// ── Module mocks ──────────────────────────────────────────────────────────────
// vi.hoisted() required for variables referenced inside vi.mock() factories (D-03-04-hoisting)

const {
  mockDeleteEvent,
  mockSetDeleteDialog,
  mockSetLastSyncedUid,
  mockSetOpenEventId,
  mockDeleteDialogOpen,
  mockDeleteDialogUid,
} = vi.hoisted(() => ({
  mockDeleteEvent: vi.fn(),
  mockSetDeleteDialog: vi.fn(),
  mockSetLastSyncedUid: vi.fn(),
  mockSetOpenEventId: vi.fn(),
  mockDeleteDialogOpen: { value: true },
  mockDeleteDialogUid: { value: 'event-uid-to-delete' },
}));

vi.mock('../store/calendarStore.js', () => ({
  useCalendarStore: (selector: (s: Record<string, unknown>) => unknown) => {
    const state = {
      deleteDialogOpen: mockDeleteDialogOpen.value,
      deleteDialogUid: mockDeleteDialogUid.value,
      setDeleteDialog: mockSetDeleteDialog,
      setLastSyncedUid: mockSetLastSyncedUid,
      setOpenEventId: mockSetOpenEventId,
    };
    return selector(state);
  },
}));

vi.mock('../api/client.js', () => ({
  deleteEvent: mockDeleteEvent,
}));

// ── Import component (after mocks) ────────────────────────────────────────────

import { DeleteConfirmationDialog } from './DeleteConfirmationDialog.js';

// ── Helpers ───────────────────────────────────────────────────────────────────

function makeQueryClient() {
  return new QueryClient({ defaultOptions: { queries: { retry: false } } });
}

function renderDialog() {
  const client = makeQueryClient();
  return render(
    <QueryClientProvider client={client}>
      <DeleteConfirmationDialog />
    </QueryClientProvider>,
  );
}

// ── Tests ─────────────────────────────────────────────────────────────────────

describe('DeleteConfirmationDialog', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    mockDeleteDialogOpen.value = true;
    mockDeleteDialogUid.value = 'event-uid-to-delete';
    mockDeleteEvent.mockResolvedValue(undefined);
  });

  it('renders heading "Delete event?"', () => {
    renderDialog();
    expect(screen.getByRole('heading', { name: /delete event\?/i })).toBeInTheDocument();
  });

  it('renders the body copy about Fastmail calendar', () => {
    renderDialog();
    expect(
      screen.getByText('This will be removed from your Fastmail calendar.'),
    ).toBeInTheDocument();
  });

  it('renders Cancel and Delete buttons', () => {
    renderDialog();
    expect(screen.getByRole('button', { name: /cancel/i })).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /^delete$/i })).toBeInTheDocument();
  });

  it('Cancel button closes dialog without deleting', () => {
    renderDialog();
    fireEvent.click(screen.getByRole('button', { name: /cancel/i }));
    expect(mockSetDeleteDialog).toHaveBeenCalledWith(false);
    expect(mockDeleteEvent).not.toHaveBeenCalled();
  });

  it('Escape key closes dialog without deleting', () => {
    renderDialog();
    fireEvent.keyDown(document, { key: 'Escape' });
    expect(mockSetDeleteDialog).toHaveBeenCalledWith(false);
    expect(mockDeleteEvent).not.toHaveBeenCalled();
  });

  it('Delete button calls deleteEvent with the uid', async () => {
    renderDialog();
    fireEvent.click(screen.getByRole('button', { name: /^delete$/i }));
    await waitFor(() => {
      expect(mockDeleteEvent).toHaveBeenCalledWith('event-uid-to-delete');
    });
  });

  it('Delete button sets lastSyncedUid to the uid', async () => {
    renderDialog();
    fireEvent.click(screen.getByRole('button', { name: /^delete$/i }));
    await waitFor(() => {
      expect(mockSetLastSyncedUid).toHaveBeenCalledWith('event-uid-to-delete');
    });
  });

  it('Delete button closes dialog and popover on success', async () => {
    renderDialog();
    fireEvent.click(screen.getByRole('button', { name: /^delete$/i }));
    await waitFor(() => {
      expect(mockSetDeleteDialog).toHaveBeenCalledWith(false);
      expect(mockSetOpenEventId).toHaveBeenCalledWith(null);
    });
  });

  it('renders nothing when deleteDialogOpen is false', () => {
    mockDeleteDialogOpen.value = false;
    const { container } = renderDialog();
    expect(container.firstChild).toBeNull();
  });

  it('has role="dialog" and aria-modal="true"', () => {
    renderDialog();
    const dialog = screen.getByRole('dialog');
    expect(dialog).toBeInTheDocument();
    expect(dialog).toHaveAttribute('aria-modal', 'true');
  });
});
