import { RetrievalOrchestrator } from '../src/retrieval/index';
import * as fs from 'fs';
import * as utils from '../src/utils';

// Mocking dependencies
jest.mock('fs');
jest.mock('../src/utils');

describe('Retrieval Orchestrator Phase 5 Integration Tests', () => {
    let orchestrator: RetrievalOrchestrator;
    const mockBrainPath = '/mock/brain';

    beforeEach(() => {
        jest.clearAllMocks();
        orchestrator = new RetrievalOrchestrator();
    });

    test('End-to-End Brain Search: should populate advanced scoring metadata in results', () => {
        // 1. Mock Brain Files
        const mockFiles = [
            '/mock/brain/doc1.md',
            '/mock/brain/doc2.md'
        ];
        (utils.findBrainFiles as jest.Mock).mockReturnValue(mockFiles);

        // 2. Mock File Content
        const fileContents: Record<string, string> = {
            '/mock/brain/doc1.md': 'Astra 성능 최적화 전략에 대한 문서입니다.',
            '/mock/brain/doc2.md': '이 설계는 기존 아키텍처와 충돌하며 오류가 많고 논란이 있는 반대 의견입니다.'
        };
        (fs.readFileSync as jest.Mock).mockImplementation((path: string) => fileContents[path]);
        (fs.statSync as jest.Mock).mockReturnValue({ mtimeMs: Date.now() });

        // 3. Perform Retrieval
        const brain = { localBrainPath: mockBrainPath };
        const result = orchestrator.retrieve('최적화 충돌', {
            brain: brain as any,
            memoryManager: {
                getLongTermMemory: () => ({ buildContext: () => null }),
                getProjectMemory: () => ({ buildContext: () => null }),
                getProceduralMemory: () => ({ buildContext: () => null }),
                getEpisodicMemory: () => ({ buildContext: () => null })
            } as any,
            contextBudget: { totalBudget: 2000 }
        });

        // 4. Verify Intelligence Metadata
        expect(result.selectedChunks.length).toBeGreaterThan(0);
        
        // Find doc2 (the conflicting one)
        const conflictChunk = result.selectedChunks.find(c => c.title.includes('doc2'));
        expect(conflictChunk).toBeDefined();
        if (conflictChunk) {
            expect(conflictChunk.metadata.conflictDetected).toBe(true);
            expect(conflictChunk.metadata.conflictSeverity).toBe('HIGH'); // '충돌', '오류', '논란', '반대' -> 4 indicators
        }

        // Find doc1 (the dense one)
        const denseChunk = result.selectedChunks.find(c => c.title.includes('doc1'));
        expect(denseChunk).toBeDefined();
        if (denseChunk) {
            expect(denseChunk.metadata.queryCoverage).toBeGreaterThan(0);
            expect(denseChunk.metadata.conflictDetected).toBe(false);
        }

        // 5. Verify Assembled Context String
        const contextString = orchestrator.buildContextString(result);
        expect(contextString).toContain('[⚠️ CONFLICT: HIGH]');
        expect(contextString).toContain('(Coverage:');
    });

    test('Score Normalization: should normalize scores across brain sources', () => {
        (utils.findBrainFiles as jest.Mock).mockReturnValue(['/mock/brain/test.md']);
        (fs.readFileSync as jest.Mock).mockReturnValue('테스트 내용');
        (fs.statSync as jest.Mock).mockReturnValue({ mtimeMs: Date.now() });

        const result = orchestrator.retrieve('테스트', {
            brain: { localBrainPath: mockBrainPath } as any,
            memoryManager: {
                getLongTermMemory: () => ({ buildContext: () => null }),
                getProjectMemory: () => ({ buildContext: () => null }),
                getProceduralMemory: () => ({ buildContext: () => null }),
                getEpisodicMemory: () => ({ buildContext: () => null })
            } as any
        });

        // Scores should be boosted by source priority (brain-memory boost is 0.9)
        const chunk = result.selectedChunks[0];
        expect(chunk.score).toBeCloseTo(0.9, 1);
    });
});
