import type { RetrievalConfig } from '@/types/app'
import { fireEvent, render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { RETRIEVE_METHOD } from '@/types/app'
import ModifyRetrievalModal from '../modify-retrieval-modal'

const { mockToast } = vi.hoisted(() => {
  const mockToast = Object.assign(vi.fn(), {
    success: vi.fn(),
    error: vi.fn(),
    warning: vi.fn(),
    info: vi.fn(),
    dismiss: vi.fn(),
    update: vi.fn(),
    promise: vi.fn(),
  })
  return { mockToast }
})

vi.mock('@langgenius/dify-ui/toast', () => ({
  toast: mockToast,
}))

vi.mock('@langgenius/dify-ui/button', () => ({
  Button: ({
    children,
    onClick,
  }: {
    children: React.ReactNode
    onClick: () => void
    variant?: string
  }) => <button onClick={onClick}>{children}</button>,
}))

vi.mock('@/app/components/datasets/common/check-rerank-model', () => ({
  isReRankModelSelected: vi.fn(() => true),
}))

vi.mock('@/app/components/datasets/common/retrieval-method-config', () => ({
  default: ({
    value,
    onChange,
  }: {
    value: RetrievalConfig
    onChange: (v: RetrievalConfig) => void
  }) => (
    <div data-testid="retrieval-method-config">
      <span>{value.search_method}</span>
      <button
        data-testid="change-config"
        onClick={() => onChange({ ...value, search_method: RETRIEVE_METHOD.hybrid })}
      >
        change
      </button>
    </div>
  ),
}))

vi.mock('@/app/components/datasets/common/economical-retrieval-method-config', () => ({
  default: () => <div data-testid="economical-config" />,
}))

vi.mock('@/app/components/header/account-setting/model-provider-page/hooks', () => ({
  useModelList: () => ({ data: [] }),
}))

vi.mock('@/context/dataset-detail', () => ({
  useDatasetDetailContextWithSelector: () => 'model-name',
}))

vi.mock('../../settings/utils', () => ({
  checkShowMultiModalTip: () => false,
}))

describe('ModifyRetrievalModal', () => {
  const defaultProps = {
    indexMethod: 'high_quality',
    value: {
      search_method: 'semantic_search',
      reranking_enable: false,
      reranking_model: {
        reranking_provider_name: '',
        reranking_model_name: '',
      },
    } as RetrievalConfig,
    isShow: true,
    onHide: vi.fn(),
    onSave: vi.fn(),
  }

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

  it('should return null when isShow is false', () => {
    const { container } = render(<ModifyRetrievalModal {...defaultProps} isShow={false} />)
    expect(container.firstChild).toBeNull()
  })

  it('should render title when isShow is true', () => {
    render(<ModifyRetrievalModal {...defaultProps} />)
    expect(screen.getByText('datasetSettings.form.retrievalSetting.title')).toBeInTheDocument()
  })

  it('should render high quality retrieval config for high_quality index', () => {
    render(<ModifyRetrievalModal {...defaultProps} />)
    expect(screen.getByTestId('retrieval-method-config')).toBeInTheDocument()
  })

  it('should render economical config for non high_quality index', () => {
    render(<ModifyRetrievalModal {...defaultProps} indexMethod="economy" />)
    expect(screen.getByTestId('economical-config')).toBeInTheDocument()
  })

  it('should call onHide when cancel button clicked', () => {
    render(<ModifyRetrievalModal {...defaultProps} />)
    fireEvent.click(screen.getByRole('button', { name: /operation\.cancel$/ }))
    expect(defaultProps.onHide).toHaveBeenCalled()
  })

  it('should call onHide when close button clicked', () => {
    render(<ModifyRetrievalModal {...defaultProps} />)
    fireEvent.click(screen.getByRole('button', { name: /operation\.close$/ }))
    expect(defaultProps.onHide).toHaveBeenCalled()
  })

  it('should call onSave with retrieval config when save clicked', () => {
    render(<ModifyRetrievalModal {...defaultProps} />)
    fireEvent.click(screen.getByRole('button', { name: /operation\.save$/ }))
    expect(defaultProps.onSave).toHaveBeenCalled()
  })

  it('should render learn more link', () => {
    render(<ModifyRetrievalModal {...defaultProps} />)
    expect(screen.getByText('datasetSettings.form.retrievalSetting.learnMore')).toBeInTheDocument()
  })
})
