import React from 'react'
import { render, fireEvent, waitFor } from '@testing-library/react'
import { AreaCascader } from '../../src/components/AreaCascader'

// Mock API调用
jest.mock('../../src/api', () => ({
  areaClient: {
    provinces: {
      $get: jest.fn().mockResolvedValue({
        status: 200,
        json: jest.fn().mockResolvedValue([
          { id: 1, name: '北京市', level: 1 },
          { id: 2, name: '上海市', level: 1 },
          { id: 3, name: '广东省', level: 1 }
        ])
      })
    },
    cities: {
      $get: jest.fn().mockImplementation(({ query }) => {
        if (query.provinceId === 1) {
          return Promise.resolve({
            status: 200,
            json: jest.fn().mockResolvedValue([
              { id: 11, name: '北京市', level: 2, parentId: 1 }
            ])
          })
        }
        if (query.provinceId === 3) {
          return Promise.resolve({
            status: 200,
            json: jest.fn().mockResolvedValue([
              { id: 31, name: '广州市', level: 2, parentId: 3 },
              { id: 32, name: '深圳市', level: 2, parentId: 3 }
            ])
          })
        }
        return Promise.resolve({
          status: 200,
          json: jest.fn().mockResolvedValue([])
        })
      })
    },
    districts: {
      $get: jest.fn().mockImplementation(({ query }) => {
        if (query.cityId === 11) {
          return Promise.resolve({
            status: 200,
            json: jest.fn().mockResolvedValue([
              { id: 111, name: '朝阳区', level: 3, parentId: 11 },
              { id: 112, name: '海淀区', level: 3, parentId: 11 }
            ])
          })
        }
        return Promise.resolve({
          status: 200,
          json: jest.fn().mockResolvedValue([])
        })
      })
    }
  }
}))

describe('AreaCascader', () => {
  beforeEach(() => {
    jest.clearAllMocks()
  })

  it('应该正确渲染初始状态', async () => {
    const { getByText } = render(<AreaCascader />)

    await waitFor(() => {
      expect(getByText('请选择省份')).toBeTruthy()
      expect(getByText('请选择城市')).toBeTruthy()
      expect(getByText('请选择区县')).toBeTruthy()
    })
  })

  it('应该加载省份列表', async () => {
    const { getByText } = render(<AreaCascader />)

    await waitFor(() => {
      expect(getByText('北京市')).toBeTruthy()
      expect(getByText('上海市')).toBeTruthy()
      expect(getByText('广东省')).toBeTruthy()
    })
  })

  it('应该在选择省份后加载城市列表', async () => {
    const { getByText } = render(<AreaCascader />)

    await waitFor(() => {
      expect(getByText('北京市')).toBeTruthy()
    })

    // 模拟选择北京市
    const beijingPicker = getByText('北京市')
    fireEvent.click(beijingPicker)

    await waitFor(() => {
      expect(getByText('北京市')).toBeTruthy() // 城市列表中的北京市
    })
  })

  it('应该在选择城市后加载区县列表', async () => {
    const { getByText } = render(<AreaCascader />)

    await waitFor(() => {
      expect(getByText('北京市')).toBeTruthy()
    })

    // 选择省份
    const beijingProvince = getByText('北京市')
    fireEvent.click(beijingProvince)

    await waitFor(() => {
      expect(getByText('北京市')).toBeTruthy() // 城市
    })

    // 选择城市
    const beijingCity = getByText('北京市')
    fireEvent.click(beijingCity)

    await waitFor(() => {
      expect(getByText('朝阳区')).toBeTruthy()
      expect(getByText('海淀区')).toBeTruthy()
    })
  })

  it('应该正确触发onChange回调', async () => {
    const mockOnChange = jest.fn()
    const { getByText } = render(
      <AreaCascader onChange={mockOnChange} />
    )

    await waitFor(() => {
      expect(getByText('北京市')).toBeTruthy()
    })

    // 选择省份
    const beijingProvince = getByText('北京市')
    fireEvent.click(beijingProvince)

    await waitFor(() => {
      expect(mockOnChange).toHaveBeenCalledWith([1])
    })
  })

  it('应该正确显示已选择的值', async () => {
    const { getByText } = render(
      <AreaCascader value={[1, 11, 111]} />
    )

    await waitFor(() => {
      expect(getByText('北京市 北京市 朝阳区')).toBeTruthy()
    })
  })

  it('应该处理空值情况', async () => {
    const { getByText } = render(<AreaCascader value={[]} />)

    await waitFor(() => {
      expect(getByText('请选择省市区')).toBeTruthy()
    })
  })
})