import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { GoodsSpecSelector } from '@/components/goods-spec-selector'
import { goodsClient } from '@/api'

// Mock API客户端
jest.mock('@/api', () => ({
  goodsClient: {
    ':id': {
      children: {
        $get: jest.fn()
      }
    }
  }
}))

// Mock Taro组件
jest.mock('@tarojs/components', () => ({
  View: ({ children, className, onClick }: any) => (
    <div className={className} onClick={onClick}>
      {children}
    </div>
  ),
  Text: ({ children, className }: any) => (
    <span className={className}>{children}</span>
  ),
  ScrollView: ({ children, className }: any) => (
    <div className={className}>{children}</div>
  ),
  Input: ({ className, type, value, onInput, onBlur, placeholder, maxlength, confirmType }: any) => (
    <input
      className={className}
      type={type}
      value={value}
      onChange={(e) => onInput?.({ detail: { value: e.target.value } })}
      onBlur={(e) => onBlur?.({ detail: { value: e.target.value } })}
      placeholder={placeholder}
      maxLength={maxlength}
      data-testid="input"
    />
  )
}))

// Mock UI组件
jest.mock('@/components/ui/button', () => ({
  Button: ({ children, onClick, className, disabled }: any) => (
    <button className={className} onClick={onClick} disabled={disabled}>
      {children}
    </button>
  )
}))

describe('GoodsSpecSelector组件', () => {
  const mockOnClose = jest.fn()
  const mockOnConfirm = jest.fn()

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

  it('当visible为false时不渲染', () => {
    const { container } = render(
      <GoodsSpecSelector
        visible={false}
        onClose={mockOnClose}
        onConfirm={mockOnConfirm}
        parentGoodsId={1}
      />
    )
    expect(container.firstChild).toBeNull()
  })

  it('当visible为true时渲染组件', () => {
    render(
      <GoodsSpecSelector
        visible={true}
        onClose={mockOnClose}
        onConfirm={mockOnConfirm}
        parentGoodsId={1}
      />
    )

    expect(screen.getByText('选择规格')).toBeInTheDocument()
    expect(screen.getByText('加载规格选项...')).toBeInTheDocument()
  })

  it('成功获取子商品列表后显示规格选项', async () => {
    // Mock成功的API响应
    const mockResponse = {
      status: 200,
      json: async () => ({
        data: [
          {
            id: 101,
            name: '红色款',
            price: 299,
            stock: 50,
            imageFile: { fullUrl: 'http://example.com/image.jpg' }
          },
          {
            id: 102,
            name: '蓝色款',
            price: 319,
            stock: 30,
            imageFile: null
          }
        ],
        total: 2,
        page: 1,
        pageSize: 100,
        totalPages: 1
      })
    }

    ;(goodsClient[':id'].children.$get as jest.Mock).mockResolvedValue(mockResponse)

    render(
      <GoodsSpecSelector
        visible={true}
        onClose={mockOnClose}
        onConfirm={mockOnConfirm}
        parentGoodsId={1}
      />
    )

    // 等待加载完成
    await waitFor(() => {
      expect(screen.getByText('红色款')).toBeInTheDocument()
    })

    expect(screen.getByText('蓝色款')).toBeInTheDocument()
    expect(screen.getByText('¥299.00')).toBeInTheDocument()
    expect(screen.getByText('库存: 50')).toBeInTheDocument()
  })

  it('API调用失败时显示错误信息', async () => {
    // Mock失败的API响应
    ;(goodsClient[':id'].children.$get as jest.Mock).mockRejectedValue(
      new Error('网络错误')
    )

    render(
      <GoodsSpecSelector
        visible={true}
        onClose={mockOnClose}
        onConfirm={mockOnConfirm}
        parentGoodsId={1}
      />
    )

    // 等待错误显示
    await waitFor(() => {
      expect(screen.getByText('网络错误')).toBeInTheDocument()
    })

    expect(screen.getByText('重试')).toBeInTheDocument()
  })

  it('没有规格选项时显示空状态', async () => {
    // Mock空响应
    const mockResponse = {
      status: 200,
      json: async () => ({
        data: [],
        total: 0,
        page: 1,
        pageSize: 100,
        totalPages: 0
      })
    }

    ;(goodsClient[':id'].children.$get as jest.Mock).mockResolvedValue(mockResponse)

    render(
      <GoodsSpecSelector
        visible={true}
        onClose={mockOnClose}
        onConfirm={mockOnConfirm}
        parentGoodsId={1}
      />
    )

    await waitFor(() => {
      expect(screen.getByText('暂无规格选项')).toBeInTheDocument()
    })
  })

  it('点击规格选项时选中该规格', async () => {
    const mockResponse = {
      status: 200,
      json: async () => ({
        data: [
          {
            id: 101,
            name: '红色款',
            price: 299,
            stock: 50,
            imageFile: null
          }
        ],
        total: 1,
        page: 1,
        pageSize: 100,
        totalPages: 1
      })
    }

    ;(goodsClient[':id'].children.$get as jest.Mock).mockResolvedValue(mockResponse)

    render(
      <GoodsSpecSelector
        visible={true}
        onClose={mockOnClose}
        onConfirm={mockOnConfirm}
        parentGoodsId={1}
      />
    )

    await waitFor(() => {
      expect(screen.getByText('红色款')).toBeInTheDocument()
    })

    // 点击规格选项
    fireEvent.click(screen.getByText('红色款'))

    // 应该显示数量选择器
    expect(screen.getByText('数量')).toBeInTheDocument()
  })

  it('点击确认按钮时调用onConfirm回调', async () => {
    const mockResponse = {
      status: 200,
      json: async () => ({
        data: [
          {
            id: 101,
            name: '红色款',
            price: 299,
            stock: 50,
            imageFile: null
          }
        ],
        total: 1,
        page: 1,
        pageSize: 100,
        totalPages: 1
      })
    }

    ;(goodsClient[':id'].children.$get as jest.Mock).mockResolvedValue(mockResponse)

    render(
      <GoodsSpecSelector
        visible={true}
        onClose={mockOnClose}
        onConfirm={mockOnConfirm}
        parentGoodsId={1}
      />
    )

    await waitFor(() => {
      expect(screen.getByText('红色款')).toBeInTheDocument()
    })

    // 选择规格
    fireEvent.click(screen.getByText('红色款'))

    // 点击确认按钮
    const confirmButton = screen.getByRole('button', { name: /确定/ })
    fireEvent.click(confirmButton)

    expect(mockOnConfirm).toHaveBeenCalledWith(
      expect.objectContaining({
        id: 101,
        name: '红色款',
        price: 299,
        stock: 50
      }),
      1,
      undefined
    )
    expect(mockOnClose).toHaveBeenCalled()
  })

  it('点击关闭按钮时调用onClose回调', () => {
    const { container } = render(
      <GoodsSpecSelector
        visible={true}
        onClose={mockOnClose}
        onConfirm={mockOnConfirm}
        parentGoodsId={1}
      />
    )

    // 点击关闭按钮（使用className查找）
    const closeButton = container.querySelector('.spec-modal-close')
    expect(closeButton).not.toBeNull()
    fireEvent.click(closeButton!)

    expect(mockOnClose).toHaveBeenCalled()
  })
})