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

// Mock API调用
jest.mock('../../src/api', () => ({
  locationClient: {
    $get: jest.fn().mockImplementation(({ query }) => {
      if (query.keyword === '北京') {
        return Promise.resolve({
          status: 200,
          json: jest.fn().mockResolvedValue([
            {
              id: 1,
              name: '北京首都国际机场',
              province: '北京市',
              city: '北京市',
              district: '朝阳区',
              address: '北京市朝阳区首都机场路'
            },
            {
              id: 2,
              name: '北京南站',
              province: '北京市',
              city: '北京市',
              district: '丰台区',
              address: '北京市丰台区永外大街12号'
            }
          ])
        })
      }
      if (query.keyword === '上海') {
        return Promise.resolve({
          status: 200,
          json: jest.fn().mockResolvedValue([
            {
              id: 3,
              name: '上海虹桥机场',
              province: '上海市',
              city: '上海市',
              district: '长宁区',
              address: '上海市长宁区虹桥路2550号'
            }
          ])
        })
      }
      return Promise.resolve({
        status: 200,
        json: jest.fn().mockResolvedValue([])
      })
    })
  }
}))

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

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

    expect(getByPlaceholderText('搜索地点')).toBeTruthy()
  })

  it('应该显示自定义占位符', () => {
    const { getByPlaceholderText } = render(
      <LocationSearch placeholder="请输入地点名称" />
    )

    expect(getByPlaceholderText('请输入地点名称')).toBeTruthy()
  })

  it('应该处理输入变化并显示搜索结果', async () => {
    const { getByPlaceholderText, getByText } = render(<LocationSearch />)

    const input = getByPlaceholderText('搜索地点')
    fireEvent.input(input, { target: { value: '北京' } })

    await waitFor(() => {
      expect(getByText('北京首都国际机场')).toBeTruthy()
      expect(getByText('北京南站')).toBeTruthy()
    })
  })

  it('应该正确选择地点并触发onChange', async () => {
    const mockOnChange = jest.fn()
    const { getByPlaceholderText, getByText } = render(
      <LocationSearch onChange={mockOnChange} />
    )

    const input = getByPlaceholderText('搜索地点')
    fireEvent.input(input, { target: { value: '北京' } })

    await waitFor(() => {
      expect(getByText('北京首都国际机场')).toBeTruthy()
    })

    const locationItem = getByText('北京首都国际机场')
    fireEvent.click(locationItem)

    expect(mockOnChange).toHaveBeenCalledWith({
      id: 1,
      name: '北京首都国际机场',
      province: '北京市',
      city: '北京市',
      district: '朝阳区',
      address: '北京市朝阳区首都机场路'
    })
  })

  it('应该支持地区筛选', async () => {
    const { getByPlaceholderText } = render(
      <LocationSearch
        areaFilter={{
          provinceId: 1,
          cityId: 11,
          districtId: 111
        }}
      />
    )

    const input = getByPlaceholderText('搜索地点')
    fireEvent.input(input, { target: { value: '北京' } })

    await waitFor(() => {
      // 验证API调用时传递了地区筛选参数
      const locationClient = require('../../src/api').locationClient
      expect(locationClient.$get).toHaveBeenCalledWith({
        query: {
          keyword: '北京',
          provinceId: 1,
          cityId: 11,
          districtId: 111
        }
      })
    })
  })

  it('应该处理清除操作', async () => {
    const mockOnChange = jest.fn()
    const { getByPlaceholderText, getByText } = render(
      <LocationSearch onChange={mockOnChange} />
    )

    const input = getByPlaceholderText('搜索地点')
    fireEvent.input(input, { target: { value: '北京' } })

    await waitFor(() => {
      expect(getByText('北京首都国际机场')).toBeTruthy()
    })

    // 选择地点
    const locationItem = getByText('北京首都国际机场')
    fireEvent.click(locationItem)

    // 清除输入
    const clearButton = getByText('×')
    fireEvent.click(clearButton)

    expect(mockOnChange).toHaveBeenCalledWith(null)
  })

  it('应该显示当前选择的地点', () => {
    const selectedLocation = {
      id: 1,
      name: '北京首都国际机场',
      province: '北京市',
      city: '北京市',
      district: '朝阳区',
      address: '北京市朝阳区首都机场路'
    }

    const { getByText } = render(
      <LocationSearch value={selectedLocation} />
    )

    expect(getByText('已选择: 北京首都国际机场 · 朝阳区 · 北京市 · 北京市')).toBeTruthy()
  })

  it('应该处理空搜索结果', async () => {
    const { getByPlaceholderText, getByText } = render(<LocationSearch />)

    const input = getByPlaceholderText('搜索地点')
    fireEvent.input(input, { target: { value: '不存在的城市' } })

    await waitFor(() => {
      expect(getByText('未找到相关地点')).toBeTruthy()
    })
  })

  it('应该处理防抖搜索', async () => {
    jest.useFakeTimers()

    const { getByPlaceholderText } = render(<LocationSearch />)
    const input = getByPlaceholderText('搜索地点')

    // 快速输入多个字符
    fireEvent.input(input, { target: { value: '北' } })
    fireEvent.input(input, { target: { value: '北京' } })
    fireEvent.input(input, { target: { value: '北京市' } })

    // 验证API只被调用一次（防抖）
    const locationClient = require('../../src/api').locationClient
    expect(locationClient.$get).not.toHaveBeenCalled()

    // 快进防抖时间
    jest.advanceTimersByTime(300)

    await waitFor(() => {
      expect(locationClient.$get).toHaveBeenCalledTimes(1)
      expect(locationClient.$get).toHaveBeenCalledWith({
        query: {
          keyword: '北京市'
        }
      })
    })

    jest.useRealTimers()
  })
})