import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { vi, test, expect, beforeEach } from 'vitest';
import FileExplorer from '../../src/components/FileExplorer';
import { listDocuments } from '../../src/api/client';

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

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

test('renders folders and files returned by listDocuments for the root path', async () => {
  vi.mocked(listDocuments).mockResolvedValue({
    folders: ['产品文档'],
    files: [{ key: '需求说明.md', name: '需求说明.md', size: 100, modifiedAt: '2026-08-01T10:00:00Z' }],
  });

  render(<FileExplorer onSelectFile={vi.fn()} selectedKey={null} />);

  expect(await screen.findByText('产品文档')).toBeInTheDocument();
  expect(await screen.findByText('需求说明.md')).toBeInTheDocument();
  expect(listDocuments).toHaveBeenCalledWith('');
});

test('clicking a file calls onSelectFile with its key', async () => {
  vi.mocked(listDocuments).mockResolvedValue({
    folders: [],
    files: [{ key: '架构设计.md', name: '架构设计.md', size: 200, modifiedAt: '2026-08-01T10:00:00Z' }],
  });
  const onSelectFile = vi.fn();

  render(<FileExplorer onSelectFile={onSelectFile} selectedKey={null} />);

  const fileRow = await screen.findByText('架构设计.md');
  fireEvent.click(fileRow);

  expect(onSelectFile).toHaveBeenCalledWith('架构设计.md');
});

test('clicking a folder loads and shows its nested contents', async () => {
  vi.mocked(listDocuments).mockImplementation((path: string) => {
    if (path === '') {
      return Promise.resolve({ folders: ['产品文档'], files: [] });
    }
    if (path === '产品文档') {
      return Promise.resolve({
        folders: [],
        files: [{ key: '产品文档/架构设计.md', name: '架构设计.md', size: 300, modifiedAt: '2026-08-01T10:00:00Z' }],
      });
    }
    return Promise.resolve({ folders: [], files: [] });
  });

  render(<FileExplorer onSelectFile={vi.fn()} selectedKey={null} />);

  const folderRow = await screen.findByText('产品文档');
  fireEvent.click(folderRow);

  expect(await screen.findByText('架构设计.md')).toBeInTheDocument();
  expect(listDocuments).toHaveBeenCalledWith('产品文档');
});

test('shows an error message when listDocuments rejects', async () => {
  vi.mocked(listDocuments).mockRejectedValue(new Error('network error'));

  render(<FileExplorer onSelectFile={vi.fn()} selectedKey={null} />);

  expect(await screen.findByTestId('file-explorer-error')).toBeInTheDocument();
});

test('changing refreshKey re-fetches the root listing', async () => {
  vi.mocked(listDocuments).mockResolvedValue({ folders: [], files: [] });

  const { rerender } = render(<FileExplorer onSelectFile={vi.fn()} selectedKey={null} refreshKey={0} />);

  await waitFor(() => {
    expect(listDocuments).toHaveBeenCalledTimes(1);
  });

  rerender(<FileExplorer onSelectFile={vi.fn()} selectedKey={null} refreshKey={1} />);

  await waitFor(() => {
    expect(listDocuments).toHaveBeenCalledTimes(2);
  });
});
