import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { vi, test, expect, beforeEach } from 'vitest';
import ReindexButton from '../../src/components/ReindexButton';
import { reindexAll } from '../../src/api/client';

vi.mock('../../src/api/client');

beforeEach(() => {
  vi.mocked(reindexAll).mockReset();
});

test('clicking the button triggers reindexAll and shows the result summary', async () => {
  vi.mocked(reindexAll).mockResolvedValue({ indexed: 5, failed: 0, total: 5 });
  const user = userEvent.setup();

  render(<ReindexButton />);
  await user.click(screen.getByRole('button', { name: '重建索引' }));

  expect(reindexAll).toHaveBeenCalledTimes(1);
  await waitFor(() => {
    expect(screen.getByTestId('reindex-message')).toHaveTextContent('已重建索引 5/5');
  });
});

test('shows an error style message when some documents fail to index', async () => {
  vi.mocked(reindexAll).mockResolvedValue({ indexed: 3, failed: 2, total: 5 });
  const user = userEvent.setup();

  render(<ReindexButton />);
  await user.click(screen.getByRole('button', { name: '重建索引' }));

  await waitFor(() => {
    const message = screen.getByTestId('reindex-message');
    expect(message).toHaveTextContent('已重建索引 3/5');
    expect(message).toHaveClass('error');
  });
});

test('shows an error message when the request fails', async () => {
  vi.mocked(reindexAll).mockRejectedValue(new Error('Failed to reindex: 500'));
  const user = userEvent.setup();

  render(<ReindexButton />);
  await user.click(screen.getByRole('button', { name: '重建索引' }));

  await waitFor(() => {
    expect(screen.getByTestId('reindex-message')).toHaveTextContent('Failed to reindex: 500');
  });
});

test('disables the button while the request is in flight', async () => {
  let resolveFn: (value: { indexed: number; failed: number; total: number }) => void = () => {};
  vi.mocked(reindexAll).mockReturnValue(
    new Promise((resolve) => {
      resolveFn = resolve;
    }),
  );
  const user = userEvent.setup();

  render(<ReindexButton />);
  const button = screen.getByRole('button', { name: '重建索引' });
  await user.click(button);

  expect(screen.getByRole('button', { name: '重建中…' })).toBeDisabled();

  resolveFn({ indexed: 1, failed: 0, total: 1 });
  await waitFor(() => {
    expect(screen.getByRole('button', { name: '重建索引' })).not.toBeDisabled();
  });
});
