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

// 完整的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 client
vi.mock('../../src/api/disabilityClient', () => {
  const mockDisabilityClient = {
    getAllDisabledPersons: {
      $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
        data: [
          {
            id: 1,
            name: '张三',
            gender: '男',
            idCard: '110101199001011234',
            disabilityId: 'D123456789',
            disabilityType: '肢体残疾',
            disabilityLevel: '一级',
            idAddress: '北京市东城区',
            phone: '13800138000',
            province: '北京市',
            city: '北京市',
            district: '东城区',
            detailedAddress: '某街道某号',
            nation: '汉族',
            isMarried: 0,
            canDirectContact: 1,
            isInBlackList: 0,
            jobStatus: 1,
            createTime: '2024-01-01T00:00:00Z',
            updateTime: '2024-01-01T00:00:00Z'
          }
        ],
        total: 1
      }))),
    },
    createDisabledPerson: {
      $post: vi.fn(() => Promise.resolve(createMockResponse(200, {
        id: 2,
        name: '李四',
        gender: '女',
        idCard: '110101199002021234',
        disabilityId: 'D123456790',
        disabilityType: '视力残疾',
        disabilityLevel: '二级',
        idAddress: '上海市黄浦区',
        phone: '13900139000',
        province: '上海市',
        city: '上海市',
        district: '黄浦区',
        detailedAddress: '某街道某号',
        nation: '汉族',
        isMarried: 1,
        canDirectContact: 1,
        isInBlackList: 0,
        jobStatus: 0,
        createTime: '2024-01-02T00:00:00Z',
        updateTime: '2024-01-02T00:00:00Z'
      }))),
    },
    updateDisabledPerson: {
      $post: vi.fn(() => Promise.resolve(createMockResponse(200, {
        id: 1,
        name: '张三（已更新）',
        gender: '男',
        idCard: '110101199001011234',
        disabilityId: 'D123456789',
        disabilityType: '肢体残疾',
        disabilityLevel: '一级',
        idAddress: '北京市东城区',
        phone: '13800138001',
        province: '北京市',
        city: '北京市',
        district: '东城区',
        detailedAddress: '更新后的地址',
        nation: '汉族',
        isMarried: 1,
        canDirectContact: 1,
        isInBlackList: 0,
        jobStatus: 1,
        createTime: '2024-01-01T00:00:00Z',
        updateTime: '2024-01-03T00:00:00Z'
      }))),
    },
    deleteDisabledPerson: {
      $post: vi.fn(() => Promise.resolve(createMockResponse(200, {
        success: true
      }))),
    },
    searchDisabledPersons: {
      $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
        data: [
          {
            id: 1,
            name: '张三',
            gender: '男',
            idCard: '110101199001011234',
            disabilityId: 'D123456789',
            disabilityType: '肢体残疾',
            disabilityLevel: '一级',
            idAddress: '北京市东城区',
            phone: '13800138000',
            province: '北京市',
            city: '北京市',
            district: '东城区',
            detailedAddress: '某街道某号',
            nation: '汉族',
            isMarried: 0,
            canDirectContact: 1,
            isInBlackList: 0,
            jobStatus: 1,
            createTime: '2024-01-01T00:00:00Z',
            updateTime: '2024-01-01T00:00:00Z'
          }
        ],
        total: 1
      }))),
    },
    getDisabledPerson: {
      ':id': {
        $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
          id: 1,
          name: '张三',
          gender: '男',
          idCard: '110101199001011234',
          disabilityId: 'D123456789',
          disabilityType: '肢体残疾',
          disabilityLevel: '一级',
          idAddress: '北京市东城区',
          phone: '13800138000',
          province: '北京市',
          city: '北京市',
          district: '东城区',
          detailedAddress: '某街道某号',
          nation: '汉族',
          isMarried: 0,
          canDirectContact: 1,
          isInBlackList: 0,
          jobStatus: 1,
          createTime: '2024-01-01T00:00:00Z',
          updateTime: '2024-01-01T00:00:00Z'
        }))),
      },
    },
  };

  const mockDisabilityClientManager = {
    get: vi.fn(() => mockDisabilityClient),
  };

  return {
    disabilityClientManager: mockDisabilityClientManager,
    disabilityClient: mockDisabilityClient,
  };
});

// Mock toast
vi.mock('sonner', () => ({
  toast: {
    success: vi.fn(),
    error: vi.fn(),
  },
}));

// Mock 枚举包
vi.mock('@d8d/allin-enums', () => ({
  DisabilityType: {
    VISION: 'vision',
    HEARING: 'hearing',
    SPEECH: 'speech',
    PHYSICAL: 'physical',
    INTELLECTUAL: 'intellectual',
    MENTAL: 'mental',
    MULTIPLE: 'multiple',
  },
  DISABILITY_TYPES: ['vision', 'hearing', 'speech', 'physical', 'intellectual', 'mental', 'multiple'],
  getDisabilityTypeLabel: vi.fn((type) => {
    const labels: Record<string, string> = {
      vision: '视力残疾',
      hearing: '听力残疾',
      speech: '言语残疾',
      physical: '肢体残疾',
      intellectual: '智力残疾',
      mental: '精神残疾',
      multiple: '多重残疾',
    };
    return labels[type] || type;
  }),
  DisabilityLevel: {
    ONE: 1,
    TWO: 2,
    THREE: 3,
    FOUR: 4,
  },
  DISABILITY_LEVELS: [1, 2, 3, 4],
  getDisabilityLevelLabel: vi.fn((level) => {
    const labels: Record<number, string> = {
      1: '一级',
      2: '二级',
      3: '三级',
      4: '四级',
    };
    return labels[level] || level.toString();
  }),
}));

// Mock 区域选择器组件
vi.mock('@d8d/area-management-ui/components', () => ({
  AreaSelect: vi.fn(({ value, onChange }) => (
    <div data-testid="area-select">
      <select
        data-testid="province-select"
        value={value?.provinceId || ''}
        onChange={(e) => onChange({ ...value, provinceId: e.target.value ? Number(e.target.value) : undefined })}
      >
        <option value="">选择省份</option>
        <option value="1">北京市</option>
      </select>
      <select
        data-testid="city-select"
        value={value?.cityId || ''}
        onChange={(e) => onChange({ ...value, cityId: e.target.value ? Number(e.target.value) : undefined })}
      >
        <option value="">选择城市</option>
        <option value="2">北京市</option>
      </select>
      <select
        data-testid="district-select"
        value={value?.districtId || ''}
        onChange={(e) => onChange({ ...value, districtId: e.target.value ? Number(e.target.value) : undefined })}
      >
        <option value="">选择区县</option>
        <option value="3">东城区</option>
      </select>
    </div>
  )),
}));

// Mock 文件选择器组件
vi.mock('@d8d/file-management-ui/components', () => ({
  FileSelector: vi.fn(({ onChange, placeholder }) => (
    <div data-testid="file-selector">
      <button
        data-testid="file-selector-button"
        onClick={() => onChange && onChange(1)}
      >
        {placeholder || '选择文件'}
      </button>
    </div>
  )),
}));

describe('残疾人个人管理集成测试', () => {
  let queryClient: QueryClient;

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

  const renderComponent = () => {
    return render(
      <QueryClientProvider client={queryClient}>
        <DisabilityPersonManagement />
      </QueryClientProvider>
    );
  };

  it('应该正确渲染残疾人列表', async () => {
    renderComponent();

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('张三')).toBeInTheDocument();
    });

    // 验证表格内容
    expect(screen.getByText('张三')).toBeInTheDocument();
    expect(screen.getByText('男')).toBeInTheDocument();
    expect(screen.getByText('110101199001011234')).toBeInTheDocument();
    expect(screen.getByText('D123456789')).toBeInTheDocument();
    expect(screen.getByText('肢体残疾')).toBeInTheDocument();
    expect(screen.getByText('一级')).toBeInTheDocument();
    expect(screen.getByText('13800138000')).toBeInTheDocument();
  });

  it('应该打开创建模态框并填写表单', async () => {
    renderComponent();

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('张三')).toBeInTheDocument();
    });

    // 点击新增按钮 - 使用测试ID
    const addButton = screen.getByTestId('add-disabled-person-button');
    fireEvent.click(addButton);

    // 验证模态框打开 - 使用测试ID
    await waitFor(() => {
      expect(screen.getByTestId('create-disabled-person-dialog-title')).toBeInTheDocument();
    });

    // 填写表单
    const nameInput = screen.getByPlaceholderText('请输入姓名');
    const idCardInput = screen.getByPlaceholderText('请输入身份证号');
    const disabilityIdInput = screen.getByPlaceholderText('请输入残疾证号');
    const phoneInput = screen.getByPlaceholderText('请输入联系电话');
    const idAddressInput = screen.getByPlaceholderText('请输入身份证地址');

    fireEvent.change(nameInput, { target: { value: '李四' } });
    fireEvent.change(idCardInput, { target: { value: '110101199002021234' } });
    fireEvent.change(disabilityIdInput, { target: { value: 'D123456790' } });
    fireEvent.change(phoneInput, { target: { value: '13900139000' } });
    fireEvent.change(idAddressInput, { target: { value: '上海市黄浦区' } });

    // 选择性别
    const genderSelect = screen.getByTestId('gender-select');
    fireEvent.change(genderSelect, { target: { value: '女' } });

    // 选择残疾类型
    const disabilityTypeSelect = screen.getByTestId('disability-type-select');
    fireEvent.change(disabilityTypeSelect, { target: { value: '视力残疾' } });

    // 选择残疾等级
    const disabilityLevelSelect = screen.getByTestId('disability-level-select');
    fireEvent.change(disabilityLevelSelect, { target: { value: '二级' } });

    // 选择省份和城市
    const provinceSelect = screen.getByTestId('province-select');
    const citySelect = screen.getByTestId('city-select');

    await act(async () => {
      fireEvent.change(provinceSelect, { target: { value: '1' } });
    });

    await act(async () => {
      fireEvent.change(citySelect, { target: { value: '2' } });
    });

    // 提交表单
    const submitButton = screen.getByText('创建');

    // 使用act包装状态更新
    await act(async () => {
      fireEvent.click(submitButton);
    });

    // 验证API调用 - 增加等待时间
    await waitFor(() => {
      const mockClient = (disabilityClientManager.get as any)();
      expect(mockClient.createDisabledPerson.$post).toHaveBeenCalled();
    }, { timeout: 3000 });

    // 验证具体的调用参数
    const mockClient = (disabilityClientManager.get as any)();
    const call = mockClient.createDisabledPerson.$post.mock.calls[0];
    expect(call).toBeDefined();

    if (call) {
      expect(call[0].json).toMatchObject({
        name: '李四',
        idCard: '110101199002021234',
        disabilityId: 'D123456790',
        phone: '13900139000',
        idAddress: '上海市黄浦区',
      });
    }
  });

  it('应该打开编辑模态框并更新数据', async () => {
    renderComponent();

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('张三')).toBeInTheDocument();
    });

    // 点击编辑按钮
    const editButton = screen.getByTestId('edit-person-1');
    fireEvent.click(editButton);

    // 验证模态框打开
    await waitFor(() => {
      expect(screen.getByText('编辑残疾人信息')).toBeInTheDocument();
    });

    // 修改电话号码
    const phoneInput = screen.getByPlaceholderText('请输入联系电话');
    fireEvent.change(phoneInput, { target: { value: '13800138001' } });

    // 提交表单
    const submitButton = screen.getByText('更新');
    fireEvent.click(submitButton);

    // 验证API调用
    await waitFor(() => {
      const mockClient = (disabilityClientManager.get as any)();
      expect(mockClient.updateDisabledPerson.$post).toHaveBeenCalledWith({
        json: expect.objectContaining({
          id: 1,
          phone: '13800138001',
        }),
      });
    });
  });

  it('应该打开查看详情模态框', async () => {
    renderComponent();

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('张三')).toBeInTheDocument();
    });

    // 点击查看按钮
    const viewButton = screen.getByTestId('view-person-1');
    fireEvent.click(viewButton);

    // 验证模态框打开并显示详情
    await waitFor(() => {
      expect(screen.getByText('残疾人详情')).toBeInTheDocument();
      expect(screen.getByText('张三')).toBeInTheDocument();
      expect(screen.getByText('110101199001011234')).toBeInTheDocument();
      expect(screen.getByText('D123456789')).toBeInTheDocument();
    });
  });

  it('应该打开删除确认对话框并删除数据', async () => {
    renderComponent();

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('张三')).toBeInTheDocument();
    });

    // 点击删除按钮
    const deleteButton = screen.getByTestId('delete-person-1');
    fireEvent.click(deleteButton);

    // 验证删除对话框打开 - 使用测试ID
    await waitFor(() => {
      expect(screen.getByTestId('delete-confirmation-dialog-title')).toBeInTheDocument();
    });

    // 确认删除 - 使用更精确的选择器
    const confirmButtons = screen.getAllByText('确认删除');
    const confirmButton = confirmButtons.find(btn => btn.getAttribute('type') === 'button' || btn.getAttribute('data-slot') === 'button') || confirmButtons[0];
    fireEvent.click(confirmButton);

    // 验证API调用
    await waitFor(() => {
      const mockClient = (disabilityClientManager.get as any)();
      expect(mockClient.deleteDisabledPerson.$post).toHaveBeenCalledWith({
        json: { id: 1 },
      });
    });
  });

  it('应该进行搜索操作', async () => {
    renderComponent();

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('张三')).toBeInTheDocument();
    });

    // 输入搜索关键词
    const searchInput = screen.getByPlaceholderText('搜索姓名或身份证号');
    fireEvent.change(searchInput, { target: { value: '张三' } });

    // 点击搜索按钮
    const searchButton = screen.getByText('搜索');
    fireEvent.click(searchButton);

    // 验证API调用
    await waitFor(() => {
      const mockClient = (disabilityClientManager.get as any)();
      expect(mockClient.getAllDisabledPersons.$get).toHaveBeenCalled();
    });
  });

  it('应该测试区域选择器集成', async () => {
    renderComponent();

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('张三')).toBeInTheDocument();
    });

    // 打开创建模态框 - 使用测试ID
    const addButton = screen.getByTestId('add-disabled-person-button');
    fireEvent.click(addButton);

    // 等待模态框打开 - 使用测试ID
    await waitFor(() => {
      expect(screen.getByTestId('create-disabled-person-dialog-title')).toBeInTheDocument();
    });

    // 验证区域选择器存在
    expect(screen.getByTestId('area-select')).toBeInTheDocument();

    // 选择省份
    const provinceSelect = screen.getByTestId('province-select');
    fireEvent.change(provinceSelect, { target: { value: '1' } });

    // 选择城市
    const citySelect = screen.getByTestId('city-select');
    fireEvent.change(citySelect, { target: { value: '2' } });

    // 选择区县
    const districtSelect = screen.getByTestId('district-select');
    fireEvent.change(districtSelect, { target: { value: '3' } });
  });

  it('应该测试文件选择器集成', async () => {
    renderComponent();

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('张三')).toBeInTheDocument();
    });

    // 打开创建模态框 - 使用测试ID
    const addButton = screen.getByTestId('add-disabled-person-button');
    fireEvent.click(addButton);

    // 等待模态框打开 - 使用测试ID
    await waitFor(() => {
      expect(screen.getByTestId('create-disabled-person-dialog-title')).toBeInTheDocument();
    });

    // 验证照片上传组件存在
    expect(screen.getByTestId('add-photo-button')).toBeInTheDocument();

    // 点击添加照片按钮
    const addPhotoButton = screen.getByTestId('add-photo-button');
    fireEvent.click(addPhotoButton);
  });

  it('应该测试枚举选择器集成', async () => {
    renderComponent();

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('张三')).toBeInTheDocument();
    });

    // 打开创建模态框 - 使用测试ID
    const addButton = screen.getByTestId('add-disabled-person-button');
    fireEvent.click(addButton);

    // 等待模态框打开 - 使用测试ID
    await waitFor(() => {
      expect(screen.getByTestId('create-disabled-person-dialog-title')).toBeInTheDocument();
    });

    // 验证残疾类型选择器 - 使用更稳健的选择器
    const disabilityTypeSelects = screen.getAllByRole('combobox');
    // 查找包含"残疾类型"标签的选择器
    const disabilityTypeSelect = disabilityTypeSelects.find(select => {
      const label = select.closest('.grid-cols-2')?.querySelector('label');
      return label?.textContent?.includes('残疾类型');
    });

    if (disabilityTypeSelect) {
      expect(disabilityTypeSelect).toBeInTheDocument();
    }

    // 验证残疾等级选择器
    const disabilityLevelSelect = disabilityTypeSelects.find(select => {
      const label = select.closest('.grid-cols-2')?.querySelector('label');
      return label?.textContent?.includes('残疾等级');
    });

    if (disabilityLevelSelect) {
      expect(disabilityLevelSelect).toBeInTheDocument();
    }
  });

  it('应该显示暂无数据提示', async () => {
    // 修改mock返回空数据
    const mockClient = (disabilityClientManager.get as any)();
    mockClient.getAllDisabledPersons.$get.mockResolvedValueOnce(
      createMockResponse(200, {
        data: [],
        total: 0
      })
    );

    renderComponent();

    // 等待暂无数据提示出现
    await waitFor(() => {
      expect(screen.getByText('暂无数据')).toBeInTheDocument();
    });

    // 验证暂无数据提示的样式
    const noDataElement = screen.getByText('暂无数据');
    expect(noDataElement).toHaveClass('text-muted-foreground');
  });
});