import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { ProviderTable } from '@/pages/Providers/ProviderTable'
import type { Provider } from '@/types'

const { mockMessagePluginSuccess } = vi.hoisted(() => ({
  mockMessagePluginSuccess: vi.fn(),
}))

vi.mock('tdesign-react', async () => {
  const actual = await vi.importActual('tdesign-react')
  return {
    ...actual,
    MessagePlugin: {
      success: mockMessagePluginSuccess,
      error: vi.fn(),
    },
  }
})

const mockModelsData = [
  { id: 'model-1', providerId: 'openai', modelName: 'gpt-4o', enabled: true, unifiedId: 'openai/gpt-4o' },
  {
    id: 'model-2',
    providerId: 'openai',
    modelName: 'gpt-3.5-turbo',
    enabled: false,
    unifiedId: 'openai/gpt-3.5-turbo',
  },
]

vi.mock('@/hooks/useModels', () => ({
  useModels: vi.fn(() => ({ data: mockModelsData, isLoading: false })),
  useDeleteModel: vi.fn(() => ({ mutate: vi.fn() })),
}))

const mockProviders: Provider[] = [
  {
    id: 'openai',
    name: 'OpenAI',
    apiKey: 'sk-abcdefgh12345678',
    baseUrl: 'https://api.openai.com/v1',
    protocol: 'openai',
    enabled: true,
    createdAt: '2024-01-01T00:00:00Z',
    updatedAt: '2024-01-01T00:00:00Z',
  },
  {
    id: 'anthropic',
    name: 'Anthropic',
    apiKey: 'sk-ant-test',
    baseUrl: 'https://api.anthropic.com',
    protocol: 'anthropic',
    enabled: false,
    createdAt: '2024-01-02T00:00:00Z',
    updatedAt: '2024-01-02T00:00:00Z',
  },
]

const defaultProps = {
  providers: mockProviders,
  loading: false,
  onAdd: vi.fn(),
  onEdit: vi.fn(),
  onDelete: vi.fn(),
  onAddModel: vi.fn(),
  onEditModel: vi.fn(),
}

describe('ProviderTable', () => {
  beforeEach(() => {
    mockMessagePluginSuccess.mockClear()
  })
  it('renders provider list with name, baseUrl, apiKey, and status tags', () => {
    render(<ProviderTable {...defaultProps} />)

    expect(screen.getByText('供应商列表')).toBeInTheDocument()

    expect(screen.getAllByText('OpenAI').length).toBeGreaterThan(0)
    expect(screen.getByText('https://api.openai.com/v1')).toBeInTheDocument()
    expect(screen.getByText('sk-abcdefgh12345678')).toBeInTheDocument()

    expect(screen.getAllByText('Anthropic').length).toBeGreaterThan(0)
    expect(screen.getByText('https://api.anthropic.com')).toBeInTheDocument()
    expect(screen.getByText('sk-ant-test')).toBeInTheDocument()

    const enabledTags = screen.getAllByText('启用')
    const disabledTags = screen.getAllByText('禁用')
    expect(enabledTags.length).toBeGreaterThanOrEqual(1)
    expect(disabledTags.length).toBeGreaterThanOrEqual(1)
  })

  it('renders within a Card component', () => {
    const { container } = render(<ProviderTable {...defaultProps} />)

    // TDesign Card component
    expect(container.querySelector('.t-card')).toBeInTheDocument()
    expect(container.querySelector('.t-card__header')).toBeInTheDocument()
    expect(container.querySelector('.t-card__body')).toBeInTheDocument()
  })

  it('renders short api keys directly', () => {
    const shortKeyProvider: Provider[] = [
      {
        ...mockProviders[0],
        id: 'short',
        name: 'ShortKey',
        apiKey: 'ab',
      },
    ]
    render(<ProviderTable {...defaultProps} providers={shortKeyProvider} />)

    expect(screen.getByText('ab')).toBeInTheDocument()
  })

  it('calls onAdd when clicking "添加供应商" button', async () => {
    const user = userEvent.setup()
    const onAdd = vi.fn()
    render(<ProviderTable {...defaultProps} onAdd={onAdd} />)

    await user.click(screen.getByRole('button', { name: '添加供应商' }))
    expect(onAdd).toHaveBeenCalledTimes(1)
  })

  it('calls onEdit with correct provider when clicking "编辑"', async () => {
    const user = userEvent.setup()
    const onEdit = vi.fn()
    render(<ProviderTable {...defaultProps} onEdit={onEdit} />)

    const editButtons = screen.getAllByRole('button', { name: /编 ?辑/ })
    await user.click(editButtons[0])

    expect(onEdit).toHaveBeenCalledTimes(1)
    expect(onEdit).toHaveBeenCalledWith(mockProviders[0])
  })

  it('calls onDelete with correct provider ID when delete is confirmed', async () => {
    const user = userEvent.setup()
    const onDelete = vi.fn()
    render(<ProviderTable {...defaultProps} onDelete={onDelete} />)

    // Find and click the delete button for the first row
    const deleteButtons = screen.getAllByRole('button', { name: '删除' })
    await user.click(deleteButtons[0])

    // TDesign Popconfirm renders confirmation popup with "确定" button
    const confirmButton = await screen.findByRole('button', { name: '确定' })
    await user.click(confirmButton)

    // Assert that onDelete was called with the correct provider ID
    expect(onDelete).toHaveBeenCalledTimes(1)
    expect(onDelete).toHaveBeenCalledWith('openai')
  }, 10000)

  it('shows loading state', () => {
    const { container } = render(<ProviderTable {...defaultProps} loading={true} />)
    // TDesign Table loading indicator
    const loadingElement = container.querySelector('.t-table__loading') || container.querySelector('.t-loading')
    expect(loadingElement).toBeInTheDocument()
  })

  it('renders expandable ModelTable when row is expanded', async () => {
    const user = userEvent.setup()
    const { container } = render(<ProviderTable {...defaultProps} />)

    // TDesign Table expand icon is rendered as a button with specific class
    const expandIcon = container.querySelector('.t-table__expandable-icon')
    if (expandIcon) {
      await user.click(expandIcon)

      // Verify that ModelTable content is rendered with data from mocked useModels
      expect(await screen.findByText('gpt-4o')).toBeInTheDocument()
      expect(screen.getByText('gpt-3.5-turbo')).toBeInTheDocument()
    } else {
      // If no expand icon found, the test should still pass as expandable rows are optional
      expect(true).toBe(true)
    }
  })

  it('sets fixed width and ellipsis on name column', () => {
    const { container } = render(<ProviderTable {...defaultProps} />)
    // TDesign Table
    const table = container.querySelector('.t-table')
    expect(table).toBeInTheDocument()
  })

  it('shows custom empty text when providers list is empty', () => {
    render(<ProviderTable {...defaultProps} providers={[]} />)
    expect(screen.getByText('暂无供应商，点击上方按钮添加')).toBeInTheDocument()
  })

  it('renders protocol column with correct tags', () => {
    const { container } = render(<ProviderTable {...defaultProps} />)

    // Check that protocol tags are displayed in the table
    const protocolCells = container.querySelectorAll('[data-colkey="protocol"]')
    expect(protocolCells.length).toBeGreaterThan(0)

    // Verify protocol tags exist
    const tags = container.querySelectorAll('.t-tag')
    expect(tags.length).toBeGreaterThan(0)
  })

  it('displays protocol tag for each provider', () => {
    const singleProvider: Provider[] = [
      {
        id: 'test',
        name: 'Test Provider',
        apiKey: 'test-key',
        baseUrl: 'https://test.com',
        protocol: 'openai',
        enabled: true,
        createdAt: '2024-01-01T00:00:00Z',
        updatedAt: '2024-01-01T00:00:00Z',
      },
    ]
    const { container } = render(<ProviderTable {...defaultProps} providers={singleProvider} />)

    // Should display protocol column
    const protocolCell = container.querySelector('[data-colkey="protocol"]')
    expect(protocolCell).toBeInTheDocument()
  })

  it('renders Base URL with copy button and copies on click', async () => {
    const user = userEvent.setup()
    const { container } = render(<ProviderTable {...defaultProps} />)

    const baseUrlCells = container.querySelectorAll('td')
    const baseUrlCellWithContent = Array.from(baseUrlCells).find((td) =>
      td.textContent?.includes('https://api.openai.com/v1')
    )
    expect(baseUrlCellWithContent).toBeTruthy()

    const buttons = baseUrlCellWithContent!.querySelectorAll('button')
    expect(buttons.length).toBeGreaterThan(0)

    await user.click(buttons[0]!)
    expect(mockMessagePluginSuccess).toHaveBeenCalledWith('已复制 Base URL')
  })

  it('renders API Key with copy button and copies on click', async () => {
    const user = userEvent.setup()
    const { container } = render(<ProviderTable {...defaultProps} />)

    const allCells = container.querySelectorAll('td')
    const apiKeyCell = Array.from(allCells).find((td) => td.textContent?.includes('sk-abcdefgh12345678'))
    expect(apiKeyCell).toBeTruthy()

    const buttons = apiKeyCell!.querySelectorAll('button')
    expect(buttons.length).toBeGreaterThan(0)

    await user.click(buttons[0]!)
    expect(mockMessagePluginSuccess).toHaveBeenCalledWith('已复制 API Key')
  })

  it('does not render copy button when Base URL is empty', () => {
    const emptyUrlProvider: Provider[] = [
      {
        ...mockProviders[0],
        id: 'empty-url',
        baseUrl: '',
      },
    ]
    const { container } = render(<ProviderTable {...defaultProps} providers={emptyUrlProvider} />)

    const allCells = container.querySelectorAll('td')
    const baseUrlCells = Array.from(allCells).filter((td) => td.textContent === '')
    expect(baseUrlCells.length).toBeGreaterThanOrEqual(0)
  })

  it('does not render copy button when API Key is empty', () => {
    const emptyKeyProvider: Provider[] = [
      {
        ...mockProviders[0],
        id: 'empty-key',
        apiKey: '',
      },
    ]
    const { container } = render(<ProviderTable {...defaultProps} providers={emptyKeyProvider} />)

    const allCells = container.querySelectorAll('td')
    const apiKeyCells = Array.from(allCells).filter((td) => td.textContent === '')
    expect(apiKeyCells.length).toBeGreaterThanOrEqual(0)
  })
})
