import { Test, TestingModule } from '@nestjs/testing';
import { RagflowSearchService } from '@/modules/knowledge-base/services/ragflow-search.service';
import { PrismaService } from '@/core/database/prisma/prisma.service';
import { RagflowService } from '@/modules/knowledge-base/services/ragflow.service';
import { MetricsService } from '@/modules/knowledge-base/services/metrics.service';

describe('RagflowSearchService', () => {
  let service: RagflowSearchService;

  const mockPrismaService: {
    ragflowDocument: { findMany: jest.Mock };
    sPDocumentIndex: { findMany: jest.Mock };
    knowledgeArticle: { findMany: jest.Mock };
    sPFolderIndex: { findMany: jest.Mock };
  } = {
    ragflowDocument: { findMany: jest.fn() },
    sPDocumentIndex: { findMany: jest.fn() },
    knowledgeArticle: { findMany: jest.fn() },
    sPFolderIndex: { findMany: jest.fn() },
  };

  const mockRagflowService: {
    resolveDatasetId: jest.Mock;
    retrieve: jest.Mock;
  } = {
    resolveDatasetId: jest.fn(),
    retrieve: jest.fn(),
  };

  const mockMetricsService: {
    logSearch: jest.Mock;
  } = {
    logSearch: jest.fn(),
  };

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        RagflowSearchService,
        {
          provide: PrismaService,
          useValue: mockPrismaService,
        },
        {
          provide: RagflowService,
          useValue: mockRagflowService,
        },
        {
          provide: MetricsService,
          useValue: mockMetricsService,
        },
      ],
    }).compile();

    service = module.get<RagflowSearchService>(RagflowSearchService);
    jest.clearAllMocks();
  });

  it('应返回文件结果后再返回文件夹结果', async () => {
    mockRagflowService.resolveDatasetId.mockResolvedValue('dataset-1');
    mockRagflowService.retrieve.mockResolvedValue({
      chunks: [
        {
          document_id: 'rf-doc-1',
          document_keyword: 'Policy A',
          content: 'Policy details',
          similarity: 0.91,
        },
      ],
    });
    mockPrismaService.ragflowDocument.findMany.mockResolvedValue([
      {
        ragflowDocumentId: 'rf-doc-1',
        sourceType: 'SP_DOCUMENT',
        sourceId: 'sp-doc-1',
      },
    ]);
    mockPrismaService.sPDocumentIndex.findMany.mockResolvedValue([
      {
        id: 'sp-doc-1',
        title: 'Employee Policy',
        webUrl: 'https://sp/doc',
        docType: 'POLICY',
        docAuthorityLevel: 'OFFICIAL',
        spModifiedAt: new Date('2026-02-20T00:00:00Z'),
        createdBy: 'Alice',
      },
    ]);
    mockPrismaService.knowledgeArticle.findMany.mockResolvedValue([]);
    mockPrismaService.sPFolderIndex.findMany.mockResolvedValue([
      {
        id: 'sp-folder-1',
        title: 'HR Policies',
        folderPath: '/Shared Documents/Policies/HR Policies',
        webUrl: 'https://sp/folder',
        createdBy: 'Bob',
        spModifiedAt: new Date('2026-02-21T00:00:00Z'),
      },
    ]);

    const result = await service.search('user-1', 'policies', 10);

    expect(result.items).toHaveLength(2);
    expect(result.items[0].type).toBe('document');
    expect(result.items[1]).toMatchObject({
      type: 'folder',
      title: 'HR Policies',
      folderPath: '/Shared Documents/Policies/HR Policies',
    });
    expect(mockMetricsService.logSearch).toHaveBeenCalledWith(
      'user-1',
      expect.objectContaining({ resultCount: 2 }),
    );
  });

  it('文件夹名精确匹配时应给出最高文件夹相关度', async () => {
    mockRagflowService.resolveDatasetId.mockResolvedValue('dataset-1');
    mockRagflowService.retrieve.mockResolvedValue({ chunks: [] });
    mockPrismaService.ragflowDocument.findMany.mockResolvedValue([]);
    mockPrismaService.sPDocumentIndex.findMany.mockResolvedValue([]);
    mockPrismaService.knowledgeArticle.findMany.mockResolvedValue([]);
    mockPrismaService.sPFolderIndex.findMany.mockResolvedValue([
      {
        id: 'sp-folder-2',
        title: 'Finance',
        folderPath: '/Shared Documents/Finance',
        webUrl: 'https://sp/folder-finance',
        createdBy: null,
        spModifiedAt: new Date('2026-02-18T00:00:00Z'),
      },
    ]);

    const result = await service.search('user-1', 'Finance', 10);

    expect(result.items).toHaveLength(1);
    expect(result.items[0]).toMatchObject({
      type: 'folder',
      title: 'Finance',
      score: 1,
    });
  });
});
