import React from 'react'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { AreaPicker } from '../../src/components/AreaPicker'

// Mock API 客户端
const mockAreaClient = {
  provinces: {
    $get: jest.fn()
  },
  cities: {
    $get: jest.fn()
  },
  districts: {
    $get: jest.fn()
  }
}

jest.mock('../../src/api', () => ({
  areaClient: mockAreaClient
}))

// 创建测试用的 QueryClient
const createTestQueryClient = () => new QueryClient({
  defaultOptions: {
    queries: {
      retry: false,
    },
  },
})

// 包装组件
const Wrapper = ({ children }: { children: React.ReactNode }) => {
  const queryClient = createTestQueryClient()
  return (
    <QueryClientProvider client={queryClient}>
      {children}
    </QueryClientProvider>
  )
}

// 模拟数据
const mockProvinces = {
  success: true,
  data: {
    provinces: [
      { id: 1, name: '北京市' },
      { id: 2, name: '上海市' },
      { id: 3, name: '广东省' }
    ]
  },
  message: ''
}

const mockCities = {
  success: true,
  data: {
    cities: [
      { id: 11, name: '北京市' },
      { id: 12, name: '朝阳区' },
      { id: 13, name: '海淀区' }
    ]
  },
  message: ''
}

const mockDistricts = {
  success: true,
  data: {
    districts: [
      { id: 101, name: '朝阳区' },
      { id: 102, name: '海淀区' },
      { id: 103, name: '西城区' }
    ]
  },
  message: ''
}

describe('AreaPicker 组件', () => {
  beforeEach(() => {
    // 重置所有 mock
    jest.clearAllMocks()

    // 设置默认的 mock 返回值
    mockAreaClient.provinces.$get.mockResolvedValue({
      status: 200,
      json: async () => mockProvinces
    })

    mockAreaClient.cities.$get.mockResolvedValue({
      status: 200,
      json: async () => mockCities
    })

    mockAreaClient.districts.$get.mockResolvedValue({
      status: 200,
      json: async () => mockDistricts
    })
  })

  test('应该正确渲染组件', async () => {
    const onClose = jest.fn()
    const onConfirm = jest.fn()

    render(
      <Wrapper>
        <AreaPicker
          visible={true}
          onClose={onClose}
          onConfirm={onConfirm}
        />
      </Wrapper>
    )

    // 检查标题
    expect(screen.getByText('选择地区')).toBeInTheDocument()

    // 检查选择器标签
    expect(screen.getByText('省份')).toBeInTheDocument()
    expect(screen.getByText('城市')).toBeInTheDocument()
    expect(screen.getByText('区县')).toBeInTheDocument()

    // 检查按钮
    expect(screen.getByText('取消')).toBeInTheDocument()
    expect(screen.getByText('确定')).toBeInTheDocument()

    // 等待数据加载
    await waitFor(() => {
      expect(mockAreaClient.provinces.$get).toHaveBeenCalled()
    })
  })

  test('应该显示自定义标题', () => {
    const onClose = jest.fn()
    const onConfirm = jest.fn()

    render(
      <Wrapper>
        <AreaPicker
          visible={true}
          onClose={onClose}
          onConfirm={onConfirm}
          title="选择出发地"
        />
      </Wrapper>
    )

    expect(screen.getByText('选择出发地')).toBeInTheDocument()
  })

  test('应该初始化选择值', async () => {
    const onClose = jest.fn()
    const onConfirm = jest.fn()

    render(
      <Wrapper>
        <AreaPicker
          visible={true}
          onClose={onClose}
          onConfirm={onConfirm}
          value={[1, 11, 101]}
        />
      </Wrapper>
    )

    // 等待数据加载
    await waitFor(() => {
      expect(mockAreaClient.provinces.$get).toHaveBeenCalled()
    })

    // 检查是否调用了城市和区县查询
    await waitFor(() => {
      expect(mockAreaClient.cities.$get).toHaveBeenCalledWith({
        query: { provinceId: 1, page: 1, pageSize: 50 }
      })
    })

    await waitFor(() => {
      expect(mockAreaClient.districts.$get).toHaveBeenCalledWith({
        query: { cityId: 11, page: 1, pageSize: 50 }
      })
    })
  })

  test('应该处理取消操作', () => {
    const onClose = jest.fn()
    const onConfirm = jest.fn()

    render(
      <Wrapper>
        <AreaPicker
          visible={true}
          onClose={onClose}
          onConfirm={onConfirm}
        />
      </Wrapper>
    )

    const cancelButton = screen.getByText('取消')
    fireEvent.click(cancelButton)

    expect(onClose).toHaveBeenCalledTimes(1)
    expect(onConfirm).not.toHaveBeenCalled()
  })

  test('应该处理确认操作', async () => {
    const onClose = jest.fn()
    const onConfirm = jest.fn()

    render(
      <Wrapper>
        <AreaPicker
          visible={true}
          onClose={onClose}
          onConfirm={onConfirm}
        />
      </Wrapper>
    )

    // 等待数据加载
    await waitFor(() => {
      expect(mockAreaClient.provinces.$get).toHaveBeenCalled()
    })

    const confirmButton = screen.getByText('确定')
    fireEvent.click(confirmButton)

    // 由于没有选择任何值，应该传递空数组
    expect(onConfirm).toHaveBeenCalledWith([], [])
    expect(onClose).toHaveBeenCalledTimes(1)
  })

  test('当不可见时应该返回 null', () => {
    const onClose = jest.fn()
    const onConfirm = jest.fn()

    const { container } = render(
      <Wrapper>
        <AreaPicker
          visible={false}
          onClose={onClose}
          onConfirm={onConfirm}
        />
      </Wrapper>
    )

    // 检查容器是否为空
    expect(container.firstChild).toBeNull()
  })

  test('应该处理 API 错误', async () => {
    // 模拟 API 错误
    mockAreaClient.provinces.$get.mockResolvedValue({
      status: 500,
      json: async () => ({ success: false, message: '服务器错误' })
    })

    const onClose = jest.fn()
    const onConfirm = jest.fn()

    render(
      <Wrapper>
        <AreaPicker
          visible={true}
          onClose={onClose}
          onConfirm={onConfirm}
        />
      </Wrapper>
    )

    // 组件应该正常渲染，即使 API 调用失败
    expect(screen.getByText('选择地区')).toBeInTheDocument()

    // 等待 API 调用
    await waitFor(() => {
      expect(mockAreaClient.provinces.$get).toHaveBeenCalled()
    })
  })

  test('应该正确显示已选择的省市区文本', async () => {
    const onClose = jest.fn()
    const onConfirm = jest.fn()

    render(
      <Wrapper>
        <AreaPicker
          visible={true}
          onClose={onClose}
          onConfirm={onConfirm}
          value={[1, 11, 101]}
        />
      </Wrapper>
    )

    // 等待数据加载
    await waitFor(() => {
      expect(mockAreaClient.provinces.$get).toHaveBeenCalled()
    })

    await waitFor(() => {
      expect(mockAreaClient.cities.$get).toHaveBeenCalled()
    })

    await waitFor(() => {
      expect(mockAreaClient.districts.$get).toHaveBeenCalled()
    })

    // 检查显示文本
    await waitFor(() => {
      expect(screen.getByText('北京市 北京市 朝阳区')).toBeInTheDocument()
    })
  })
})