import { render, fireEvent, waitFor } from '@testing-library/react'
import { mockShowToast } from '~/__mocks__/taroMock'
import CancelReasonDialog from '@/components/common/CancelReasonDialog'

describe('CancelReasonDialog', () => {
  const defaultProps = {
    open: true,
    onOpenChange: jest.fn(),
    onConfirm: jest.fn(),
    loading: false
  }

  beforeEach(() => {
    jest.clearAllMocks()
  })

  it('应该渲染对话框当可见时为true', () => {
    const { getByText, getAllByText } = render(<CancelReasonDialog {...defaultProps} />)

    expect(getByText('取消订单')).toBeTruthy()
    expect(getByText('请选择或填写取消原因，这将帮助我们改进服务')).toBeTruthy()
    expect(getByText('我不想买了')).toBeTruthy()
    expect(getByText('信息填写错误，重新下单')).toBeTruthy()
    expect(getByText('商家缺货')).toBeTruthy()
    expect(getByText('价格不合适')).toBeTruthy()
    // 有多个"其他原因"文本，使用getAllByText
    expect(getAllByText('其他原因').length).toBeGreaterThan(0)
  })

  it('不应该渲染对话框当open为false时', () => {
    const { queryByText } = render(
      <CancelReasonDialog {...defaultProps} open={false} />
    )

    expect(queryByText('取消订单')).toBeNull()
  })

  it.each([
    '我不想买了',
    '信息填写错误，重新下单',
    '商家缺货',
    '价格不合适',
    '其他原因'
  ])('应该选择预定义原因 %s 当点击时', async (reason) => {
    const { getByTestId } = render(<CancelReasonDialog {...defaultProps} />)

    const reasonOption = getByTestId(`cancel-reason-${reason}`)
    fireEvent.click(reasonOption)

    // 等待状态更新完成
    await waitFor(() => {
      expect(reasonOption).toHaveClass('border-primary')
    })

    const confirmButton = getByTestId('confirm-cancel-button')
    fireEvent.click(confirmButton)

    expect(defaultProps.onConfirm).toHaveBeenCalledWith(reason)
  })

  it('应该显示选中状态当点击预定义原因时', async () => {
    const { getByTestId } = render(<CancelReasonDialog {...defaultProps} />)

    // 点击第一个原因
    const firstReason = getByTestId('cancel-reason-我不想买了')
    fireEvent.click(firstReason)

    // 等待状态更新完成
    await waitFor(() => {
      // 验证选中状态样式
      expect(firstReason).toHaveClass('border-primary')
      expect(firstReason).toHaveClass('bg-primary/10')
    })

    // 点击第二个原因，第一个应该取消选中
    const secondReason = getByTestId('cancel-reason-信息填写错误，重新下单')
    fireEvent.click(secondReason)

    // 等待状态更新完成
    await waitFor(() => {
      // 第一个原因应该不再有选中状态
      expect(firstReason).not.toHaveClass('border-primary')
      expect(firstReason).not.toHaveClass('bg-primary/10')

      // 第二个原因应该有选中状态
      expect(secondReason).toHaveClass('border-primary')
      expect(secondReason).toHaveClass('bg-primary/10')
    })
  })

  it('应该清除预定义原因选中状态当输入自定义原因时', async () => {
    const { getByTestId, getByPlaceholderText } = render(<CancelReasonDialog {...defaultProps} />)

    // 先点击一个预定义原因
    const reasonOption = getByTestId('cancel-reason-我不想买了')
    fireEvent.click(reasonOption)

    // 等待选中状态更新
    await waitFor(() => {
      // 验证有选中状态
      expect(reasonOption).toHaveClass('border-primary')
      expect(reasonOption).toHaveClass('bg-primary/10')
    })

    // 输入自定义原因
    const input = getByPlaceholderText('请输入其他取消原因...')
    fireEvent.input(input, { target: { value: '自定义取消原因' } })

    // 等待选中状态清除
    await waitFor(() => {
      // 预定义原因的选中状态应该被清除
      expect(reasonOption).not.toHaveClass('border-primary')
      expect(reasonOption).not.toHaveClass('bg-primary/10')
    })
  })

  it('应该模拟用户实际点击流程', async () => {
    const { getByTestId } = render(<CancelReasonDialog {...defaultProps} />)

    // 点击一个原因
    const reasonOption = getByTestId('cancel-reason-商家缺货')
    fireEvent.click(reasonOption)

    // 等待选中状态
    await waitFor(() => {
      expect(reasonOption).toHaveClass('border-primary')
      expect(reasonOption).toHaveClass('bg-primary/10')
    })

    // 立即点击确认按钮
    const confirmButton = getByTestId('confirm-cancel-button')
    fireEvent.click(confirmButton)

    // 应该成功调用onConfirm
    expect(defaultProps.onConfirm).toHaveBeenCalledWith('商家缺货')
  })

  it('应该调用onConfirm当确认按钮被点击时', () => {
    const { getByTestId } = render(<CancelReasonDialog {...defaultProps} />)

    const reasonOption = getByTestId('cancel-reason-我不想买了')
    fireEvent.click(reasonOption)

    const confirmButton = getByTestId('confirm-cancel-button')
    fireEvent.click(confirmButton)

    expect(defaultProps.onConfirm).toHaveBeenCalledWith('我不想买了')
  })

  it('应该调用onOpenChange当取消按钮被点击时', () => {
    const { getByText } = render(<CancelReasonDialog {...defaultProps} />)

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

    expect(defaultProps.onOpenChange).toHaveBeenCalledWith(false)
  })

  it('应该显示错误当确认空原因时', () => {
    const { getByTestId, getByText } = render(<CancelReasonDialog {...defaultProps} />)

    const confirmButton = getByTestId('confirm-cancel-button')
    fireEvent.click(confirmButton)

    // 使用更精确的查询方式查找错误消息
    const errorMessage = getByText('请输入取消原因')
    expect(errorMessage).toBeTruthy()
    expect(defaultProps.onConfirm).not.toHaveBeenCalled()
  })

  it('应该显示错误当原因超过200字符时', () => {
    const { getByPlaceholderText, getByTestId, getByText } = render(
      <CancelReasonDialog {...defaultProps} />
    )

    const input = getByPlaceholderText('请输入其他取消原因...')
    fireEvent.input(input, { target: { value: 'a'.repeat(201) } })

    const confirmButton = getByTestId('confirm-cancel-button')
    fireEvent.click(confirmButton)

    const errorMessage = getByText('取消原因不能超过200个字符')
    expect(errorMessage).toBeTruthy()
    expect(defaultProps.onConfirm).not.toHaveBeenCalled()
  })

  it('应该处理自定义原因输入', () => {
    const { getByPlaceholderText, getByTestId } = render(
      <CancelReasonDialog {...defaultProps} />
    )

    const input = getByPlaceholderText('请输入其他取消原因...')
    fireEvent.input(input, { target: { value: '自定义取消原因' } })

    const confirmButton = getByTestId('confirm-cancel-button')
    fireEvent.click(confirmButton)

    expect(defaultProps.onConfirm).toHaveBeenCalledWith('自定义取消原因')
  })

  it('应该显示加载状态当loading为true时', () => {
    const { getByTestId } = render(
      <CancelReasonDialog {...defaultProps} loading={true} />
    )

    const confirmButton = getByTestId('confirm-cancel-button')
    expect(confirmButton).toHaveTextContent('提交中...')
  })

  it('应该禁用按钮当loading为true时', () => {
    const { getByText, getByTestId } = render(
      <CancelReasonDialog {...defaultProps} loading={true} />
    )

    const cancelButton = getByText('取消')
    const confirmButton = getByTestId('confirm-cancel-button')

    // 检查按钮是否被禁用
    expect(cancelButton).toBeTruthy()
    expect(confirmButton).toBeTruthy()
  })

  it('应该重置状态当对话框关闭时', () => {
    const { getByTestId, getByText, rerender } = render(
      <CancelReasonDialog {...defaultProps} />
    )

    const reasonOption = getByTestId('cancel-reason-我不想买了')
    fireEvent.click(reasonOption)

    // 重新渲染关闭的对话框
    rerender(<CancelReasonDialog {...defaultProps} open={false} />)

    // 重新渲染打开的对话框
    rerender(<CancelReasonDialog {...defaultProps} open={true} />)

    // 检查状态是否重置 - 直接点击确认按钮应该显示错误
    const confirmButton = getByTestId('confirm-cancel-button')
    fireEvent.click(confirmButton)

    const errorMessage = getByText('请输入取消原因')
    expect(errorMessage).toBeTruthy()
  })
})