import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { AdvertisementTypeSelector } from '../../src/components/AdvertisementTypeSelector'
import { advertisementTypeClient } from '../../src/api/advertisementTypeClient'

// Mock the advertisement type client
vi.mock('../../src/api/advertisementTypeClient', () => {
  const advertisementTypeClient = {
    index: {
      $get: vi.fn(),
    },
  }
  return {
    advertisementTypeClient,
    advertisementTypeClientManager: {
      get: vi.fn(() => advertisementTypeClient),
    },
  }
})

const mockAdvertisementTypes = {
  data: [
    { id: 1, name: '首页轮播', code: 'home_carousel', status: 1, createdAt: '2024-01-01' },
    { id: 2, name: '侧边广告', code: 'sidebar_ad', status: 1, createdAt: '2024-01-01' },
    { id: 3, name: '弹窗广告', code: 'popup_ad', status: 0, createdAt: '2024-01-01' },
  ],
  pagination: {
    total: 3,
    page: 1,
    pageSize: 10,
    totalPages: 1,
  },
}

const TestWrapper = ({ children }: { children: React.ReactNode }) => {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: {
        retry: false,
      },
    },
  })

  return (
    <QueryClientProvider client={queryClient}>
      {children as any}
    </QueryClientProvider>
  )
}

describe('AdvertisementTypeSelector 集成测试', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('应该正确渲染广告类型选择器', async () => {
    (advertisementTypeClient.index.$get as any).mockResolvedValue({
      status: 200,
      json: async () => mockAdvertisementTypes,
    })

    render(
      <TestWrapper>
        <AdvertisementTypeSelector testId="advertisement-type-selector" />
      </TestWrapper>
    )

    // 验证加载状态
    expect(screen.getByTestId('advertisement-type-selector')).toBeInTheDocument()
    expect(screen.getByText('加载中...')).toBeInTheDocument()

    // 等待数据加载完成
    await waitFor(() => {
      expect(screen.getByText('请选择广告类型')).toBeInTheDocument()
    })

    // 点击选择器打开下拉菜单
    const selectTrigger = screen.getByTestId('advertisement-type-selector')
    fireEvent.click(selectTrigger)

    // 验证下拉菜单中的选项
    await waitFor(() => {
      expect(screen.getByText('首页轮播')).toBeInTheDocument()
      expect(screen.getByText('侧边广告')).toBeInTheDocument()
      expect(screen.getByText('弹窗广告')).toBeInTheDocument()
    })
  })

  it('应该处理加载状态', () => {
    // Mock 延迟响应
    (advertisementTypeClient.index.$get as any).mockImplementation(
      () => new Promise(() => {}) // 永不解析的Promise
    )

    render(
      <TestWrapper>
        <AdvertisementTypeSelector testId="advertisement-type-selector" />
      </TestWrapper>
    )

    // 验证加载状态
    expect(screen.getByTestId('advertisement-type-selector')).toBeInTheDocument()
    expect(screen.getByText('加载中...')).toBeInTheDocument()
  })

  it('应该处理错误状态', async () => {
    (advertisementTypeClient.index.$get as any).mockRejectedValue(new Error('API错误'))

    render(
      <TestWrapper>
        <AdvertisementTypeSelector testId="advertisement-type-selector" />
      </TestWrapper>
    )

    // 等待错误状态
    await waitFor(() => {
      expect(screen.getByText('加载广告类型失败')).toBeInTheDocument()
    })
  })

  it('应该处理选择器值变化', async () => {
    (advertisementTypeClient.index.$get as any).mockResolvedValue({
      status: 200,
      json: async () => mockAdvertisementTypes,
    })

    const mockOnChange = vi.fn()

    render(
      <TestWrapper>
        <AdvertisementTypeSelector onChange={mockOnChange} testId="advertisement-type-selector" />
      </TestWrapper>
    )

    // 等待数据加载完成
    await waitFor(() => {
      expect(screen.getByTestId('advertisement-type-selector')).toBeEnabled()
    })

    // 点击选择器打开下拉菜单
    const selectTrigger = screen.getByTestId('advertisement-type-selector')
    fireEvent.click(selectTrigger)

    // 选择第一个选项
    await waitFor(() => {
      const firstOption = screen.getByText('首页轮播')
      fireEvent.click(firstOption)
    })

    // 验证onChange被调用
    expect(mockOnChange).toHaveBeenCalledWith(1)
  })

  it('应该支持自定义占位符', async () => {
    (advertisementTypeClient.index.$get as any).mockResolvedValue({
      status: 200,
      json: async () => mockAdvertisementTypes,
    })

    render(
      <TestWrapper>
        <AdvertisementTypeSelector placeholder="选择广告分类" testId="advertisement-type-selector" />
      </TestWrapper>
    )

    // 等待数据加载完成
    await waitFor(() => {
      expect(screen.getByText('选择广告分类')).toBeInTheDocument()
    })
  })

  it('应该支持禁用状态', async () => {
    (advertisementTypeClient.index.$get as any).mockResolvedValue({
      status: 200,
      json: async () => mockAdvertisementTypes,
    })

    render(
      <TestWrapper>
        <AdvertisementTypeSelector disabled={true} testId="advertisement-type-selector" />
      </TestWrapper>
    )

    // 等待数据加载完成
    await waitFor(() => {
      const selectTrigger = screen.getByTestId('advertisement-type-selector')
      expect(selectTrigger).toBeDisabled()
    })
  })

  it('应该支持预选值', async () => {
    (advertisementTypeClient.index.$get as any).mockResolvedValue({
      status: 200,
      json: async () => mockAdvertisementTypes,
    })

    render(
      <TestWrapper>
        <AdvertisementTypeSelector value={2} testId="advertisement-type-selector" />
      </TestWrapper>
    )

    // 等待数据加载完成
    await waitFor(() => {
      expect(screen.getByTestId('advertisement-type-selector')).toBeEnabled()
    })

    // 验证预选值已正确设置
    // 在Radix UI Select中，预选值会显示在选择器触发器中
    const selectTrigger = screen.getByTestId('advertisement-type-selector')
    expect(selectTrigger).toHaveTextContent('侧边广告')
  })
})