/**
 * Pack-5 (session c93b3449) Calendar wiring tests:
 *  - R3FE-002: onReschedule is passed to CalendarView — dropping an entry
 *    onto a new day issues router.patch(calendar.update) with the new date
 *  - R3FE-003: onStatusChange + onEdit are passed to EventCard — clicking
 *    "Mark Complete" in list view issues router.patch(calendar.updateStatus)
 *  - R3UXS-016: header-readout counts (Total + Overdue) shown instead of grid
 *  - R3UXS-020: all button/sheet/empty-state labels read "Add task"
 */
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi, beforeEach } from 'vitest';

// ─── hoist CalendarView onReschedule capture ──────────────────────────────
const capturedReschedule = { fn: null as ((entryId: string, newDate: string) => void) | null };

vi.mock('@/Components/Calendar/CalendarView', () => ({
  default: ({
    entries,
    onReschedule,
  }: {
    entries: unknown[];
    onReschedule?: (entryId: string, newDate: string) => void;
  }) => {
    capturedReschedule.fn = onReschedule ?? null;
    return (
      <div data-testid="calendar-view">
        Calendar View: {entries.length} entries
        <button
          data-testid="simulate-drop"
          onClick={() => onReschedule?.('entry-1', '2026-06-15')}
        >
          Simulate drag-drop
        </button>
      </div>
    );
  },
}));

// ─── hoist EventCard onStatusChange + onEdit capture ─────────────────────
const capturedStatusChange = {
  fn: null as ((entry: { id: string; title: string; status: string; page_url: string | null; description: string | null; due_date: string; scheduled_date: string | null; source_type: string | null; source_id: number | null; metadata: Record<string, unknown> | null }, newStatus: string) => void) | null,
};
const capturedOnEdit = { fn: null as ((entry: unknown) => void) | null };

vi.mock('@/Components/Calendar/EventCard', () => ({
  default: ({
    entry,
    onStatusChange,
    onEdit,
  }: {
    entry: { id: string; title: string; status: string; page_url: string | null; description: string | null; due_date: string; scheduled_date: string | null; source_type: string | null; source_id: number | null; metadata: Record<string, unknown> | null };
    onStatusChange?: (entry: unknown, newStatus: string) => void;
    onEdit?: (entry: unknown) => void;
  }) => {
    capturedStatusChange.fn = onStatusChange
      ? (e, s) => onStatusChange(e, s)
      : null;
    capturedOnEdit.fn = onEdit ?? null;
    return (
      <div data-testid={`event-card-${entry.id}`}>
        {entry.title}
        {entry.status !== 'completed' && onStatusChange && (
          <button
            data-testid={`mark-complete-${entry.id}`}
            onClick={() => onStatusChange(entry, 'completed')}
          >
            Mark Complete
          </button>
        )}
        {onEdit && (
          <button
            data-testid={`edit-${entry.id}`}
            onClick={() => onEdit(entry)}
          >
            Edit
          </button>
        )}
      </div>
    );
  },
}));

import { router } from '@inertiajs/react';

import CalendarIndex from './Index';

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    usePage: vi.fn(() => ({
      props: {
        auth: { user: { name: 'Test User', email: 'test@example.com' } },
        features: { billing: false, notifications: false },
        sites: [],
        limits: null,
        ai_defaults: { model: 'gpt-4o-mini', temperature: 0.7 },
        polling_interval_ms: 5000,
      },
    })),
    Head: ({ title }: { title: string }) => <title>{title}</title>,
    Link: ({ children, href }: { children: React.ReactNode; href: string }) => (
      <a href={href}>{children}</a>
    ),
    router: {
      get: vi.fn(),
      patch: vi.fn(),
      post: vi.fn(),
      on: vi.fn(() => vi.fn()),
    },
    useForm: vi.fn(() => ({
      data: {
        title: '',
        description: '',
        scheduled_date: '',
        status: 'planned',
        page_url: '',
      },
      setData: vi.fn(),
      post: vi.fn(),
      patch: vi.fn(),
      processing: false,
      errors: {},
      reset: vi.fn(),
    })),
  };
});

vi.mock('@/Components/theme/use-theme', () => ({
  useTheme: vi.fn(() => ({ theme: 'system', setTheme: vi.fn(), resolvedTheme: 'light' })),
}));

vi.mock('@/Components/Shared/InertiaPagination', () => ({
  default: () => <div data-testid="pagination">Pagination</div>,
}));

vi.mock('@/Components/ui/empty-state', () => ({
  EmptyState: ({
    title,
    primaryAction,
  }: {
    title: string;
    primaryAction?: { label: string; onClick?: () => void };
  }) => (
    <div data-testid="empty-state">
      <h3>{title}</h3>
      {primaryAction && (
        <button onClick={primaryAction.onClick}>{primaryAction.label}</button>
      )}
    </div>
  ),
}));

const site = { id: '1', name: 'Test Site', domain: 'https://test.com' };

const entry1 = {
  id: 'entry-1',
  title: 'Refresh Homepage',
  description: 'Update stale content',
  due_date: '2026-06-10',
  scheduled_date: null,
  status: 'planned' as const,
  source_type: null,
  source_id: null,
  page_url: 'https://test.com/',
  metadata: null,
};

const defaultEntries = {
  data: [entry1],
  links: [] as Array<{ url: string | null; label: string; active: boolean }>,
  current_page: 1,
  last_page: 1,
};

const defaultCounts = { total: 1, planned: 1, in_progress: 0, completed: 0, overdue: 0 };
const defaultFilters = {
  status: null,
  source_type: null,
  start_date: null,
  end_date: null,
  sort_by: null,
};

describe('Calendar/Index – pack-5', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    capturedReschedule.fn = null;
    capturedStatusChange.fn = null;
    capturedOnEdit.fn = null;
  });

  // ── R3FE-002 ──────────────────────────────────────────────────────────────

  describe('R3FE-002: onReschedule wired to CalendarView', () => {
    it('passes onReschedule to CalendarView', () => {
      render(
        <CalendarIndex
          site={site}
          entries={defaultEntries}
          filters={defaultFilters}
          counts={defaultCounts}
        />,
      );

      // CalendarView mock captures onReschedule — it must be set (not null)
      expect(capturedReschedule.fn).toBeTypeOf('function');
    });

    it('fires router.patch(calendar.update) with new scheduled_date when onReschedule is called', async () => {
      const user = userEvent.setup();
      render(
        <CalendarIndex
          site={site}
          entries={defaultEntries}
          filters={defaultFilters}
          counts={defaultCounts}
        />,
      );

      // Click the simulated drag-drop button inside the CalendarView mock
      await user.click(screen.getByTestId('simulate-drop'));

      // router.patch must have been called once
      const patchCalls = vi.mocked(router.patch).mock.calls;
      expect(patchCalls.length).toBe(1);

      // URL should target calendar.update
      expect((patchCalls[0][0] as string)).toContain('calendar');
      // Payload must contain the new scheduled_date
      expect((patchCalls[0][1] as Record<string, string>).scheduled_date).toBe('2026-06-15');
    });
  });

  // ── R3FE-003 ──────────────────────────────────────────────────────────────

  describe('R3FE-003: onStatusChange + onEdit wired to EventCard in list view', () => {
    const renderListView = async () => {
      const user = userEvent.setup();
      const rendered = render(
        <CalendarIndex
          site={site}
          entries={defaultEntries}
          filters={defaultFilters}
          counts={defaultCounts}
        />,
      );
      // Switch to list view
      await user.click(screen.getByRole('tab', { name: /List View/i }));
      return { user, ...rendered };
    };

    it('passes onStatusChange to EventCard in list view', async () => {
      await renderListView();
      expect(capturedStatusChange.fn).toBeTypeOf('function');
    });

    it('passes onEdit to EventCard in list view', async () => {
      await renderListView();
      expect(capturedOnEdit.fn).toBeTypeOf('function');
    });

    it('renders "Mark Complete" button in list view for non-completed entry', async () => {
      await renderListView();
      expect(screen.getByTestId('mark-complete-entry-1')).toBeInTheDocument();
    });

    it('fires router.patch(calendar.updateStatus) with status=completed when Mark Complete is clicked', async () => {
      const { user } = await renderListView();

      await user.click(screen.getByTestId('mark-complete-entry-1'));

      const patchCalls = vi.mocked(router.patch).mock.calls;
      expect(patchCalls.length).toBe(1);

      // URL should reference calendar + updateStatus
      const url = patchCalls[0][0] as string;
      expect(url).toContain('calendar');
      // Payload must have status: 'completed'
      expect((patchCalls[0][1] as Record<string, string>).status).toBe('completed');
    });

    it('renders Edit button in list view', async () => {
      await renderListView();
      expect(screen.getByTestId('edit-entry-1')).toBeInTheDocument();
    });
  });

  // ── R3UXS-016: no stats grid ──────────────────────────────────────────────

  describe('R3UXS-016: stats grid replaced by header readouts', () => {
    it('shows Total count in EditorialPageHeader readout', () => {
      render(
        <CalendarIndex
          site={site}
          entries={defaultEntries}
          filters={defaultFilters}
          counts={defaultCounts}
        />,
      );

      // "Total" label should be present (now in the header readout)
      expect(screen.getByText('Total')).toBeInTheDocument();
    });

    it('shows Overdue count in EditorialPageHeader readout when overdue > 0', () => {
      render(
        <CalendarIndex
          site={site}
          entries={defaultEntries}
          filters={defaultFilters}
          counts={{ ...defaultCounts, overdue: 2 }}
        />,
      );

      expect(screen.getByText('Overdue')).toBeInTheDocument();
    });

    it('does not render the old 5-card grid (Planned / In Progress / Completed cards)', () => {
      render(
        <CalendarIndex
          site={site}
          entries={defaultEntries}
          filters={defaultFilters}
          counts={defaultCounts}
        />,
      );

      // Old stats grid had individual "Planned", "In Progress", "Completed" cards
      // These should no longer be present as standalone stat cards
      // (they may appear in filters/badges but not as stat grid labels)
      expect(screen.queryByText('In Progress')).not.toBeInTheDocument();
      expect(screen.queryByText('Completed')).not.toBeInTheDocument();
    });
  });

  // ── R3UXS-020: "Add task" verb standardisation ────────────────────────────

  describe('R3UXS-020: "Add task" verb throughout', () => {
    it('header button reads "Add task"', () => {
      render(
        <CalendarIndex
          site={site}
          entries={defaultEntries}
          filters={defaultFilters}
          counts={defaultCounts}
        />,
      );

      // The header action button should say "Add task" not "Create Task"
      expect(screen.getByRole('button', { name: /Add task/i })).toBeInTheDocument();
      expect(screen.queryByRole('button', { name: /Create Task/i })).not.toBeInTheDocument();
    });

    it('empty-state CTA reads "Add task"', () => {
      render(
        <CalendarIndex
          site={site}
          entries={{ data: [], links: [], current_page: 1, last_page: 1 }}
          filters={defaultFilters}
          counts={{ total: 0, planned: 0, in_progress: 0, completed: 0, overdue: 0 }}
        />,
      );

      // "Add task" appears at least once (header button + empty-state CTA)
      // Both must read "Add task" not "Create Task" per R3UXS-020
      const addTaskElements = screen.getAllByText('Add task');
      expect(addTaskElements.length).toBeGreaterThanOrEqual(1);
    });
  });
});
