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 { FileManagement } from '../../src/components/FileManagement';

// 完整的mock响应对象
const createMockResponse = (status: number, data?: any) => ({
  status,
  ok: status >= 200 && status < 300,
  body: null,
  bodyUsed: false,
  statusText: status === 200 ? 'OK' : status === 201 ? 'Created' : status === 204 ? 'No Content' : 'Error',
  headers: new Headers(),
  url: '',
  redirected: false,
  type: 'basic' as ResponseType,
  json: async () => data || {},
  text: async () => '',
  blob: async () => new Blob(),
  arrayBuffer: async () => new ArrayBuffer(0),
  formData: async () => new FormData(),
  clone: function() { return this; }
});

// Mock API客户端
vi.mock('../../src/api/fileClient', () => {
  const mockFileClient = {
    index: {
      $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
        data: [],
        pagination: { current: 1, pageSize: 10, total: 0 }
      }))),
    },
    ':id': {
      $put: vi.fn(() => Promise.resolve(createMockResponse(200, {}))),
      $delete: vi.fn(() => Promise.resolve(createMockResponse(204, {}))),
    },
  };

  const mockFileClientManager = {
    get: vi.fn(() => mockFileClient),
  };

  return {
    fileClientManager: mockFileClientManager,
    fileClient: mockFileClient,
  };
});

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

describe('FileManagement', () => {
  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>
    );
  };

  it('应该渲染文件管理组件', () => {
    renderWithQueryClient(<FileManagement />);

    expect(screen.getByText('文件管理')).toBeInTheDocument();
    expect(screen.getByText('上传文件')).toBeInTheDocument();
    expect(screen.getByText('文件列表')).toBeInTheDocument();
  });

  it('应该显示搜索功能', () => {
    renderWithQueryClient(<FileManagement showSearch={true} />);

    expect(screen.getByPlaceholderText('搜索文件名称或类型')).toBeInTheDocument();
    expect(screen.getByText('搜索')).toBeInTheDocument();
  });

  it('应该隐藏搜索功能', () => {
    renderWithQueryClient(<FileManagement showSearch={false} />);

    expect(screen.queryByPlaceholderText('搜索文件名称或类型')).not.toBeInTheDocument();
    expect(screen.queryByText('搜索')).not.toBeInTheDocument();
  });

  it('应该隐藏上传按钮', () => {
    renderWithQueryClient(<FileManagement showUploadButton={false} />);

    expect(screen.queryByText('上传文件')).not.toBeInTheDocument();
  });

  it('应该打开上传对话框', async () => {
    renderWithQueryClient(<FileManagement />);

    const uploadButton = screen.getByTestId('upload-file-button');
    fireEvent.click(uploadButton);

    await waitFor(() => {
      expect(screen.getByTestId('upload-file-dialog')).toBeInTheDocument();
      expect(screen.getByRole('heading', { name: '上传文件' })).toBeInTheDocument();
      expect(screen.getByTestId('minio-uploader')).toBeInTheDocument();
    });
  });

  it('应该显示加载状态', async () => {
    // Mock API调用返回加载状态
    const { fileClient } = await import('../../src/api/fileClient');
    (fileClient.index.$get as any).mockReturnValue(new Promise(() => {}));

    renderWithQueryClient(<FileManagement />);

    expect(screen.getByRole('table')).toBeInTheDocument();
  });

  it('应该显示空状态', async () => {
    const { fileClient } = await import('../../src/api/fileClient');
    (fileClient.index.$get as any).mockResolvedValue(createMockResponse(200, {
      data: [],
      pagination: { current: 1, pageSize: 10, total: 0 }
    }));

    renderWithQueryClient(<FileManagement />);

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