/**
 * ============================================================
 * Memory Extractor (기억 추출기)
 * 
 * 대화 종료 시 히스토리를 분석하여 각 메모리 레이어에 
 * 저장할 정보를 자동으로 추출합니다.
 * LLM 호출 없이 패턴 매칭 기반으로 동작합니다.
 * ============================================================
 */

import { LongTermMemory } from './LongTermMemory';
import { ProjectMemory } from './ProjectMemory';
import { EpisodicMemory } from './EpisodicMemory';

interface ExtractionResult {
    longTermCandidates: number;
    episodeCreated: boolean;
    projectUpdated: boolean;
}

export class MemoryExtractor {

    /**
     * 세션 종료 시 모든 메모리 레이어에 대해 추출을 수행합니다.
     */
    public extractFromSession(
        sessionId: string,
        messages: Array<{ role: string; content: string; timestamp?: number }>,
        longTermMemory: LongTermMemory,
        episodicMemory: EpisodicMemory,
        projectMemory: ProjectMemory | null,
        projectContext?: string
    ): ExtractionResult {
        const result: ExtractionResult = {
            longTermCandidates: 0,
            episodeCreated: false,
            projectUpdated: false
        };

        // 1. Long-Term Memory 추출
        // 자동 추출 항목엔 TTL(14일)을 부여 — 참조될 때마다 슬라이딩 연장되므로 실제로
        // 쓰이는 지식은 살아남고, 한 번 들어온 일회성·잡음 내용은 14일 뒤 자연 소멸한다.
        // (에러 로그/실패 데이터는 extractCandidates 단계에서 이미 걸러짐.)
        const candidates = LongTermMemory.extractCandidates(messages);
        const expiresAt = Date.now() + LongTermMemory.AUTO_EXTRACT_TTL_MS;
        for (const candidate of candidates) {
            longTermMemory.addEntry(
                candidate.category,
                candidate.content,
                `session:${sessionId}`,
                0.7,  // 자동 추출이므로 기본 신뢰도 0.7
                { expiresAt },
            );
        }
        result.longTermCandidates = candidates.length;

        // 2. Episodic Memory 생성
        const episode = episodicMemory.createEpisode(
            sessionId,
            messages,
            projectContext
        );
        result.episodeCreated = !!episode;

        // 3. Project Memory 업데이트 (프로젝트 관련 대화인 경우)
        if (projectMemory && projectContext) {
            const updated = this.extractProjectInfo(messages, projectMemory);
            result.projectUpdated = updated;
        }

        return result;
    }

    /**
     * 대화에서 프로젝트 관련 정보를 추출하여 Project Memory에 저장합니다.
     */
    private extractProjectInfo(
        messages: Array<{ role: string; content: string }>,
        projectMemory: ProjectMemory
    ): boolean {
        let updated = false;
        const allText = messages.map((m) => m.content).join('\n');

        // Tech stack 추출
        const techPatterns = [
            /(?:사용|using|사용하는|tech\s*stack|기술\s*스택)[\s:：]*([^\n]+)/gi
        ];
        for (const pattern of techPatterns) {
            let match;
            while ((match = pattern.exec(allText)) !== null) {
                const techs = match[1]
                    .split(/[,，\s]+/)
                    .filter((t) => t.length >= 2 && t.length <= 20);
                for (const tech of techs) {
                    projectMemory.addTechStack(tech.trim());
                    updated = true;
                }
            }
        }

        // Bug report 추출
        const bugPatterns = [
            /(?:버그|bug|오류|error|이슈|issue)[\s:：]+(.{10,200})/gi
        ];
        for (const pattern of bugPatterns) {
            let match;
            while ((match = pattern.exec(allText)) !== null) {
                // 간단한 버그만 자동 기록 (상세 분석은 사용자 확인 필요)
                // 여기서는 패턴만 감지하고, 실제 기록은 사용자 확인 후
                updated = true;
            }
        }

        if (updated) {
            projectMemory.save();
        }

        return updated;
    }
}
