import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import type { WorkSession } from '@solelog/shared';
import History from './History';
import { apiFetch } from '../lib/api';
import { downloadExport } from '../lib/export';

// Mock the network layer so no real requests are made.
vi.mock('../lib/api', () => ({
  apiFetch: vi.fn(),
}));

// Mock the authenticated CSV download helper.
vi.mock('../lib/export', () => ({
  downloadExport: vi.fn(),
}));

const mockedApiFetch = vi.mocked(apiFetch);
const mockedDownloadExport = vi.mocked(downloadExport);

function session(overrides: Partial<WorkSession> = {}): WorkSession {
  return {
    id: 1,
    user_id: 'u1',
    activity_id: 1,
    activity_name: 'Frezen',
    insole_type: 'Kurk',
    pair_count: 2,
    start_time: '2026-01-02T08:30:00.000Z',
    end_time: '2026-01-02T09:31:01.000Z',
    duration_seconds: 3661,
    paused_seconds: 0,
    paused_at: null,
    status: 'completed',
    source: 'app',
    notes: null,
    created_at: '2026-01-02T08:30:00.000Z',
    ...overrides,
  };
}

function renderHistory() {
  const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  return render(
    <QueryClientProvider client={queryClient}>
      <History />
    </QueryClientProvider>,
  );
}

describe('History', () => {
  beforeEach(() => {
    mockedApiFetch.mockReset();
    mockedDownloadExport.mockReset();
    mockedApiFetch.mockResolvedValue([]);
    mockedDownloadExport.mockResolvedValue(undefined);
  });

  afterEach(() => {
    vi.clearAllMocks();
  });

  it('renders the header and export button in Dutch', () => {
    renderHistory();
    expect(screen.getByText('Geschiedenis')).toBeInTheDocument();
    expect(screen.getByRole('button', { name: 'Exporteer CSV' })).toBeInTheDocument();
  });

  it('shows the empty state when there are no sessions', async () => {
    mockedApiFetch.mockResolvedValue([]);
    renderHistory();
    expect(await screen.findByText('Nog geen opgeslagen sessies.')).toBeInTheDocument();
  });

  it('renders a session card with activity name, type, count and duration', async () => {
    mockedApiFetch.mockResolvedValue([session({ duration_seconds: 3661 })]);
    renderHistory();

    expect(await screen.findByText('Frezen')).toBeInTheDocument();
    const card = screen.getByText('Frezen').closest('.session-card') as HTMLElement;
    expect(card).not.toBeNull();
    expect(card.textContent).toContain('Kurk');
    expect(card.textContent).toContain('2 inlegzolen');
    // 3661s -> "1h 1m" (hours present).
    expect(card.textContent).toContain('1h 1m');
  });

  it('uses the singular noun for a count of 1', async () => {
    mockedApiFetch.mockResolvedValue([session({ pair_count: 1 })]);
    renderHistory();

    const card = (await screen.findByText('Frezen')).closest('.session-card') as HTMLElement;
    expect(card.textContent).toContain('1 inlegzool');
    expect(card.textContent).not.toContain('1 inlegzolen');
  });

  it('renders a Pauze line when paused_seconds > 0', async () => {
    mockedApiFetch.mockResolvedValue([session({ paused_seconds: 125 })]);
    renderHistory();

    const card = (await screen.findByText('Frezen')).closest('.session-card') as HTMLElement;
    // 125s -> "2m 5s".
    expect(card.textContent).toContain('Pauze 2m 5s');
  });

  it('does not render a Pauze line when paused_seconds is 0', async () => {
    mockedApiFetch.mockResolvedValue([session({ paused_seconds: 0 })]);
    renderHistory();

    const card = (await screen.findByText('Frezen')).closest('.session-card') as HTMLElement;
    expect(card.textContent).not.toContain('Pauze');
  });

  it('triggers the CSV download on Exporteer CSV', async () => {
    const user = userEvent.setup();
    renderHistory();

    await user.click(screen.getByRole('button', { name: 'Exporteer CSV' }));
    expect(mockedDownloadExport).toHaveBeenCalledTimes(1);
  });
});
