import type { KnowledgeBaseNodeType } from './types'
import type { ModelItem } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { CommonNodeType } from '@/app/components/workflow/types'
import { render, screen } from '@testing-library/react'
import {
  ConfigurationMethodEnum,
  ModelStatusEnum,
  ModelTypeEnum,
} from '@/app/components/header/account-setting/model-provider-page/declarations'
import { BlockEnum } from '@/app/components/workflow/types'
import Node from './node'
import {
  ChunkStructureEnum,
  IndexMethodEnum,
  RetrievalSearchMethodEnum,
} from './types'

const mockUseModelList = vi.hoisted(() => vi.fn())
const mockUseSettingsDisplay = vi.hoisted(() => vi.fn())
const mockUseEmbeddingModelStatus = vi.hoisted(() => vi.fn())

vi.mock('@tanstack/react-query', async (importOriginal) => {
  const actual = await importOriginal<typeof import('@tanstack/react-query')>()
  return {
    ...actual,
    useQuery: () => ({ data: undefined }),
  }
})

vi.mock('@/app/components/header/account-setting/model-provider-page/hooks', async (importOriginal) => {
  const actual = await importOriginal<typeof import('@/app/components/header/account-setting/model-provider-page/hooks')>()
  return {
    ...actual,
    useLanguage: () => 'en_US',
    useModelList: mockUseModelList,
  }
})

vi.mock('./hooks/use-settings-display', () => ({
  useSettingsDisplay: mockUseSettingsDisplay,
}))

vi.mock('./hooks/use-embedding-model-status', () => ({
  useEmbeddingModelStatus: mockUseEmbeddingModelStatus,
}))

const createModelItem = (overrides: Partial<ModelItem> = {}): ModelItem => ({
  model: 'text-embedding-3-large',
  label: { en_US: 'Text Embedding 3 Large', zh_Hans: 'Text Embedding 3 Large' },
  model_type: ModelTypeEnum.textEmbedding,
  fetch_from: ConfigurationMethodEnum.predefinedModel,
  status: ModelStatusEnum.active,
  model_properties: {},
  load_balancing_enabled: false,
  ...overrides,
})

const createNodeData = (overrides: Partial<CommonNodeType<KnowledgeBaseNodeType>> = {}): CommonNodeType<KnowledgeBaseNodeType> => ({
  title: 'Knowledge Base',
  desc: '',
  type: BlockEnum.KnowledgeBase,
  index_chunk_variable_selector: ['result'],
  chunk_structure: ChunkStructureEnum.general,
  indexing_technique: IndexMethodEnum.QUALIFIED,
  embedding_model: 'text-embedding-3-large',
  embedding_model_provider: 'openai',
  keyword_number: 10,
  retrieval_model: {
    top_k: 3,
    score_threshold_enabled: false,
    score_threshold: 0.5,
    search_method: RetrievalSearchMethodEnum.semantic,
  },
  ...overrides,
})

describe('KnowledgeBaseNode', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mockUseModelList.mockReturnValue({ data: [] })
    mockUseSettingsDisplay.mockReturnValue({
      [IndexMethodEnum.QUALIFIED]: 'High Quality',
      [RetrievalSearchMethodEnum.semantic]: 'Vector Search',
    })
    mockUseEmbeddingModelStatus.mockReturnValue({
      providerMeta: undefined,
      modelProvider: undefined,
      currentModel: createModelItem(),
      status: 'active',
    })
  })

  // Embedding model row should mirror the selector status labels.
  describe('Embedding Model Status', () => {
    it('should render active embedding model label when the model is available', () => {
      render(<Node id="knowledge-base-1" data={createNodeData()} />)

      expect(screen.getByText('Text Embedding 3 Large')).toBeInTheDocument()
    })

    it('should render configure required when embedding model status requires configuration', () => {
      mockUseEmbeddingModelStatus.mockReturnValue({
        providerMeta: undefined,
        modelProvider: undefined,
        currentModel: createModelItem({ status: ModelStatusEnum.noConfigure }),
        status: 'configure-required',
      })

      render(<Node id="knowledge-base-1" data={createNodeData()} />)

      expect(screen.getByText('common.modelProvider.selector.configureRequired')).toBeInTheDocument()
    })

    it('should render disabled when embedding model status is disabled', () => {
      mockUseEmbeddingModelStatus.mockReturnValue({
        providerMeta: undefined,
        modelProvider: undefined,
        currentModel: createModelItem({ status: ModelStatusEnum.disabled }),
        status: 'disabled',
      })

      render(<Node id="knowledge-base-1" data={createNodeData()} />)

      expect(screen.getByText('common.modelProvider.selector.disabled')).toBeInTheDocument()
    })

    it('should render incompatible when embedding model status is incompatible', () => {
      mockUseEmbeddingModelStatus.mockReturnValue({
        providerMeta: undefined,
        modelProvider: undefined,
        currentModel: undefined,
        status: 'incompatible',
      })

      render(<Node id="knowledge-base-1" data={createNodeData()} />)

      expect(screen.getByText('common.modelProvider.selector.incompatible')).toBeInTheDocument()
    })

    it('should render configure model prompt when no embedding model is selected', () => {
      mockUseEmbeddingModelStatus.mockReturnValue({
        providerMeta: undefined,
        modelProvider: undefined,
        currentModel: undefined,
        status: 'empty',
      })

      render(
        <Node
          id="knowledge-base-1"
          data={createNodeData({
            embedding_model: undefined,
            embedding_model_provider: undefined,
          })}
        />,
      )

      expect(screen.getByText('plugin.detailPanel.configureModel')).toBeInTheDocument()
    })
  })
})
