import { describe, it, expect, vi } from 'vitest';
import { screen, waitFor } from '@testing-library/react';
import { http, HttpResponse } from 'msw';
import { server } from '../mocks/server';
import type { ComponentType } from 'react';
import { renderWithProviders } from '../utils/renderWithProviders';

export interface ListPageTestConfig {
  /** 页面组件 */
  Component: ComponentType;
  /** 列表 API 路径（如 '/api/v1/health/patients'） */
  apiPath: string;
  /** 表格列名数组 — 用于验证表头 */
  columns: string[];
  /** 第一条 mock 数据中会被渲染到表格的文本 */
  firstRowTexts: string[];
  /** mock 数据总条数 */
  totalItems: number;
  /** 是否有「新建」按钮 */
  hasCreateButton?: boolean;
  /** 新建按钮文本（默认 "新建"） */
  createButtonText?: string;
  /** 是否有搜索/筛选 */
  hasSearch?: boolean;
  /** 是否有分页（默认 true） */
  hasPagination?: boolean;
  /** 自定义路由（默认 '/'） */
  route?: string;
  /** 自定义 mock 数据（默认使用空数组 + totalItems） */
  mockItems?: Record<string, unknown>[];
  /** 额外测试用例 */
  extraTests?: () => void;
}

export function createListPageTests(config: ListPageTestConfig) {
  const {
    Component,
    apiPath,
    columns,
    totalItems,
    hasCreateButton = true,
    createButtonText = '新建',
    hasSearch = true,
    hasPagination = true,
    route = '/',
    extraTests,
  } = config;

  describe(`${Component.displayName || Component.name || 'ListPage'}`, () => {
    function setupMock(items?: Record<string, unknown>[], total?: number) {
      const mockData = items ?? config.mockItems ?? [];
      const mockTotal = total ?? totalItems;
      server.use(
        http.get(apiPath, () =>
          HttpResponse.json({
            success: true,
            data: { data: mockData, total: mockTotal, page: 1, page_size: 20, total_pages: Math.ceil(mockTotal / 20) },
          }),
        ),
      );
    }

    it('渲染加载状态并显示数据', async () => {
      vi.setConfig({ testTimeout: 15000 });
      setupMock(config.mockItems);
      renderWithProviders(<Component />, { route });

      await waitFor(() => {
        const table = document.querySelector('.ant-table');
        expect(table).toBeInTheDocument();
      });
    });

    it('表格包含正确的列名', async () => {
      setupMock(config.mockItems);
      renderWithProviders(<Component />, { route });

      await waitFor(() => {
        const headers = document.querySelectorAll('th');
        const headerTexts = Array.from(headers).map((h) => h.textContent?.trim());
        for (const col of columns) {
          expect(headerTexts.some((t) => t?.includes(col))).toBe(true);
        }
      });
    });

    if (hasPagination && totalItems > 20) {
      it('分页器显示正确的总数', async () => {
        setupMock(config.mockItems, totalItems);
        renderWithProviders(<Component />, { route });

        await waitFor(() => {
          const pagination = document.querySelector('.ant-pagination');
          expect(pagination).toBeInTheDocument();
        });
      });
    }

    if (hasCreateButton) {
      it('显示新建按钮', async () => {
        setupMock(config.mockItems);
        renderWithProviders(<Component />, { route });

        await waitFor(() => {
          const btn = screen.getByRole('button', { name: new RegExp(createButtonText) });
          expect(btn).toBeInTheDocument();
        });
      });
    }

    if (hasSearch) {
      it('搜索/筛选区域存在', async () => {
        setupMock(config.mockItems);
        renderWithProviders(<Component />, { route });

        await waitFor(() => {
          const table = document.querySelector('.ant-table');
          expect(table).toBeInTheDocument();
        });
        const inputs = document.querySelectorAll('input, .ant-select, .ant-picker');
        expect(inputs.length).toBeGreaterThan(0);
      });
    }

    if (extraTests) {
      extraTests();
    }
  });
}
