import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import FileSelector from '../../src/components/FileSelector';

// Mock API客户端
vi.mock('../../src/api/fileClient', () => ({
  fileClient: {
    $get: vi.fn(),
    ':id': {
      $get: vi.fn(),
    },
  },
}));

// Mock 文件上传组件
vi.mock('../../src/components/MinioUploader', () => ({
  default: () => <div data-testid="minio-uploader">MinioUploader</div>,
}));

describe('FileSelector', () => {
  let queryClient: QueryClient;

  beforeEach(() => {
    queryClient = new QueryClient({
      defaultOptions: {
        queries: { retry: false },
        mutations: { retry: false },
      },
    });

    vi.clearAllMocks();
  });

  const renderWithQueryClient = (component: React.ReactElement) => {
    return render(
      <QueryClientProvider client={queryClient}>
        {component}
      </QueryClientProvider>
    );
  };

  const mockFiles = [
    {
      id: 1,
      name: 'test-image.jpg',
      type: 'image/jpeg',
      size: 1024,
      fullUrl: 'http://example.com/test-image.jpg',
      uploadTime: '2024-01-01T00:00:00Z',
    },
    {
      id: 2,
      name: 'test-document.pdf',
      type: 'application/pdf',
      size: 2048,
      fullUrl: 'http://example.com/test-document.pdf',
      uploadTime: '2024-01-01T00:00:00Z',
    },
  ];

  it('应该渲染文件选择器', () => {
    renderWithQueryClient(
      <FileSelector value={null} onChange={() => {}} />
    );

    expect(screen.getByText('选择文件')).toBeInTheDocument();
  });

  it('应该打开选择对话框', async () => {
    const { fileClient } = require('../../src/api/fileClient');
    fileClient.$get.mockResolvedValue({
      ok: true,
      json: async () => ({
        data: mockFiles,
        pagination: { current: 1, pageSize: 50, total: 2 }
      })
    });

    renderWithQueryClient(
      <FileSelector value={null} onChange={() => {}} />
    );

    const selectButton = screen.getByText('选择文件');
    fireEvent.click(selectButton);

    await waitFor(() => {
      expect(screen.getByText('选择文件')).toBeInTheDocument();
      expect(screen.getByText('上传新文件或从已有文件中选择')).toBeInTheDocument();
    });
  });

  it('应该显示已选文件预览', async () => {
    const { fileClient } = require('../../src/api/fileClient');
    fileClient[':id'].$get.mockResolvedValue({
      ok: true,
      json: async () => mockFiles[0]
    });

    renderWithQueryClient(
      <FileSelector value={1} onChange={() => {}} showPreview={true} />
    );

    await waitFor(() => {
      expect(screen.getByText('更换文件')).toBeInTheDocument();
    });
  });

  it('应该支持多选模式', async () => {
    const { fileClient } = require('../../src/api/fileClient');
    fileClient.$get.mockResolvedValue({
      ok: true,
      json: async () => ({
        data: mockFiles,
        pagination: { current: 1, pageSize: 50, total: 2 }
      })
    });

    const onChange = vi.fn();
    renderWithQueryClient(
      <FileSelector
        value={[1, 2]}
        onChange={onChange}
        allowMultiple={true}
        showPreview={true}
      />
    );

    await waitFor(() => {
      expect(screen.getByText('已选择 2 个文件')).toBeInTheDocument();
    });
  });

  it('应该过滤文件类型', async () => {
    const { fileClient } = require('../../src/api/fileClient');
    fileClient.$get.mockResolvedValue({
      ok: true,
      json: async () => ({
        data: mockFiles,
        pagination: { current: 1, pageSize: 50, total: 2 }
      })
    });

    renderWithQueryClient(
      <FileSelector
        value={null}
        onChange={() => {}}
        filterType="image"
      />
    );

    const selectButton = screen.getByText('选择文件');
    fireEvent.click(selectButton);

    await waitFor(() => {
      expect(fileClient.$get).toHaveBeenCalledWith({
        query: {
          page: 1,
          pageSize: 50,
          keyword: 'image'
        }
      });
    });
  });

  it('应该处理文件选择确认', async () => {
    const { fileClient } = require('../../src/api/fileClient');
    fileClient.$get.mockResolvedValue({
      ok: true,
      json: async () => ({
        data: mockFiles,
        pagination: { current: 1, pageSize: 50, total: 2 }
      })
    });

    const onChange = vi.fn();
    renderWithQueryClient(
      <FileSelector value={null} onChange={onChange} />
    );

    const selectButton = screen.getByText('选择文件');
    fireEvent.click(selectButton);

    await waitFor(() => {
      const fileItems = screen.getAllByText('test-image.jpg');
      fireEvent.click(fileItems[0]);
    });

    const confirmButton = screen.getByText('确认选择');
    fireEvent.click(confirmButton);

    expect(onChange).toHaveBeenCalledWith(1);
  });
});