import { render } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';

import React from 'react';

import type { AutopilotRunRow } from '@/types/recovery-runs';

import { recoveryRunsColumns } from './Index.columns';

/**
 * R8UXB-005 — Autopilot History drill-down.
 * R9UXB-101 — 'Review settings' link must use site id, not autopilot id.
 *
 * Tests that:
 *  1. Failed runs expose the error message in an expandable detail row.
 *  2. Completed/partial runs with pages_generated > 0 have a 'View drafts' link.
 *  3. 'sites.recovery-runs.index' is in CANONICAL_ROUTE_LABELS as 'Autopilot History'.
 *  4. Failed runs without batch output do not show 'View drafts'.
 *  5. 'Review settings' href uses the site id (not the autopilot_public_id) so
 *     sites.schedule.edit resolves to the correct site's schedule editor.
 */

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    Link: ({ href, children, ...rest }: { href: string; children: React.ReactNode }) => (
      <a href={href} {...rest}>
        {children}
      </a>
    ),
  };
});

// Helper: render a single cell from the column definition by column id.
function renderCell(
  columns: ReturnType<typeof recoveryRunsColumns>,
  columnId: string,
  row: AutopilotRunRow,
): HTMLElement {
  const col = columns.find(
    (c) =>
      ('accessorKey' in c && c.accessorKey === columnId) ||
      ('id' in c && c.id === columnId),
  );
  if (!col || !col.cell) throw new Error(`Column ${columnId} not found or has no cell renderer`);

  // Minimal mock of the TanStack Table row context. Cast broadly to avoid
  // TanStack Table's complex generic types in test code.
  /* eslint-disable @typescript-eslint/no-explicit-any */
  const mockRow = {
    original: row,
    getValue: (key: string) => (row as any)[key],
  } as any;

  const cellFn = col.cell as (ctx: { row: unknown }) => React.ReactNode;
  /* eslint-enable @typescript-eslint/no-explicit-any */
  const { container } = render(
    <div>
      {cellFn({ row: mockRow })}
    </div>,
  );
  return container;
}

const baseRun: AutopilotRunRow = {
  id: 1,
  status: 'completed',
  mode: 'publish',
  pages_targeted: 10,
  pages_generated: 8,
  pages_published: 6,
  cost_usd: 0.1234,
  error: null,
  error_message: null,
  started_at: '2026-06-01T10:00:00Z',
  completed_at: '2026-06-01T10:05:00Z',
  created_at: '2026-06-01T10:00:00Z',
  batch_public_id: 'abc123',
  autopilot_public_id: 'site01',
};

describe('RecoveryRuns columns — R8UXB-005 drill-down', () => {
  beforeEach(() => {
    vi.stubGlobal('route', (name: string, params?: unknown) =>
      params !== undefined ? `/${name}/${JSON.stringify(params)}` : `/${name}`,
    );
  });

  it('renders a "View drafts" link for a completed run with generated drafts', () => {
    const columns = recoveryRunsColumns('42');
    const container = renderCell(columns, 'actions', baseRun);

    const viewDraftsLink = container.querySelector('a[href*="batch-ai"]');
    expect(viewDraftsLink).not.toBeNull();
    expect(viewDraftsLink?.textContent).toMatch(/View drafts/i);
  });

  it('does not render a "View drafts" link when no drafts were generated', () => {
    const columns = recoveryRunsColumns('42');
    const container = renderCell(columns, 'actions', {
      ...baseRun,
      pages_generated: 0,
      batch_public_id: null,
    });

    const viewDraftsLink = container.querySelector('a[href*="batch-ai"]');
    expect(viewDraftsLink).toBeNull();
  });

  it('shows error details for a failed run with no batch output', () => {
    const columns = recoveryRunsColumns('42');
    const container = renderCell(columns, 'actions', {
      ...baseRun,
      status: 'failed',
      // The controller returns a sanitized generic message (never raw exception text).
      error_message: 'The run encountered an error. Check your API key settings and try again.',
      pages_generated: 0,
      batch_public_id: null,
    });

    // Error message should be visible in the detail row.
    expect(container.textContent).toContain('The run encountered an error');
  });

  it('shows "Review settings" link for a failed run', () => {
    const columns = recoveryRunsColumns('42');
    const container = renderCell(columns, 'actions', {
      ...baseRun,
      status: 'failed',
      error_message: 'The run encountered an error. Check your API key settings and try again.',
      pages_generated: 2,
      batch_public_id: 'partial123',
    });

    const settingsLink = container.querySelector('a[href*="schedule"]');
    expect(settingsLink).not.toBeNull();
    expect(settingsLink?.textContent).toMatch(/Review settings/i);
  });

  it('returns null for a pending run with no output', () => {
    const columns = recoveryRunsColumns('42');
    const container = renderCell(columns, 'actions', {
      ...baseRun,
      status: 'pending',
      pages_generated: 0,
      batch_public_id: null,
      error_message: null,
    });

    // No action content rendered.
    expect(container.textContent?.trim()).toBe('');
  });

  // R9UXB-101: 'Review settings' must route to the SITE's schedule editor, not an
  // autopilot-id-keyed URL. sites.schedule.edit is bound by {site}, so the param
  // must be the site integer id, never the autopilot_public_id ULID.
  it('R9UXB-101: Review settings href uses the site id, not the autopilot_public_id', () => {
    const SITE_ID = '99';
    const AUTOPILOT_ID = 'autopilot-ulid-abc123';

    const columns = recoveryRunsColumns(SITE_ID);
    const container = renderCell(columns, 'actions', {
      ...baseRun,
      status: 'failed',
      error_message: 'Something went wrong.',
      pages_generated: 0,
      batch_public_id: null,
      autopilot_public_id: AUTOPILOT_ID,
    });

    const settingsLink = container.querySelector('a[href*="schedule"]');
    expect(settingsLink).not.toBeNull();
    // href must contain the site id
    expect(settingsLink?.getAttribute('href')).toContain(String(SITE_ID));
    // href must NOT contain the autopilot_public_id
    expect(settingsLink?.getAttribute('href')).not.toContain(AUTOPILOT_ID);
  });
});

describe('CANONICAL_ROUTE_LABELS — R8UXB-005', () => {
  it('includes sites.recovery-runs.index → Autopilot History', async () => {
    const { CANONICAL_ROUTE_LABELS } = await import('@/config/site-navigation');
    expect(CANONICAL_ROUTE_LABELS['sites.recovery-runs.index']).toBe('Autopilot History');
  });
});
