import { logInfo } from '../utils';

export class AgentDataValidator {
    /**
     * 에이전트 간 핸드오프(Handoff) 시 데이터 무결성을 검증하고 품질 점수를 반환합니다.
     */
    public static validateHandoff(stage: string, data: string): { score: number, conflictRisk: number } {
        if (!data || data.trim().length === 0) {
            throw new Error(`[IntegrityError] 데이터 누락: ${stage} 에이전트의 출력이 비어 있습니다.`);
        }

        const minLength = process.env.NODE_ENV === 'test' ? 5 : 50;
        
        switch (stage.toLowerCase()) {
            case 'planner':
                if (data.length < minLength) {
                    throw new Error(`[IntegrityError] Planner 출력 데이터가 비정상적으로 짧습니다 (${data.length} chars). 계획 누락 의심.`);
                }
                break;
            case 'researcher':
                if (data.length < minLength) {
                    throw new Error(`[IntegrityError] Researcher 출력 데이터가 부족합니다 (${data.length} chars). 근거 데이터 누락 의심.`);
                }
                break;
            case 'writer':
                if (data.length < minLength) {
                    throw new Error(`[IntegrityError] Writer 결과물이 불완전합니다 (${data.length} chars). 최종 보고서 작성 실패 의심.`);
                }
                break;
            case 'outline':
                // Outline 응답은 JSON 배열 — 빈 배열 `[]` (single-pass 신호) 도 유효.
                // 길이 검증을 우회하고, 형식 검사는 호출자(`parseOutline`) 가 별도로 한다.
                break;
            case 'direct':
                // 짧은 질문에 대한 짧은 답을 허용. 한 문장(≈ 10자) 까지 OK.
                if (data.length < 4) {
                    throw new Error(`[IntegrityError] Direct 답변이 비정상적으로 짧습니다 (${data.length} chars).`);
                }
                break;
            default:
                if (data.length < 10) {
                    throw new Error(`[IntegrityError] ${stage} 에이전트로부터 유효한 응답을 받지 못했습니다.`);
                }
                break;
        }
        
        // 품질 점수화 (Quality Scoring)
        const score = QualityScorer.evaluate(data);
        if (score < 50) {
            logInfo(`[QualityWarning] ${stage} 결과 품질 낮음 (Score: ${score}). 내용 보강이 필요할 수 있습니다.`);
        }

        // [New] 지능형 충돌 감지 및 위험도 평가
        const conflictRisk = ConflictDetector.analyzeSemanticDivergence(data);
        if (conflictRisk > 40) {
            logInfo(`[ConflictAlert] ${stage} 단계에서 지식 충돌 위험 감지 (Risk: ${conflictRisk}).`);
        }

        return { score, conflictRisk };
    }

    /**
     * [New] 오류 발생 시 안전하게 데이터를 진단합니다 (에러를 던지지 않음).
     */
    public static audit(stage: string, data: string): { score: number, conflictRisk: number, issues: string[] } {
        const issues: string[] = [];
        if (!data || data.trim().length === 0) {
            issues.push('데이터가 완전히 비어 있음');
            return { score: 0, conflictRisk: 100, issues };
        }

        if (data.length < 50) issues.push('데이터 길이가 너무 짧음 (잠재적 누락)');
        
        const score = QualityScorer.evaluate(data);
        const conflictRisk = ConflictDetector.analyzeSemanticDivergence(data);
        
        if (score < 40) issues.push('품질 점수 매우 낮음');
        if (conflictRisk > 60) issues.push('심각한 지식 충돌 감지');

        return { score, conflictRisk, issues };
    }
}

export class QualityScorer {
    /**
     * 수집된 데이터의 품질을 휴리스틱하게 점수화합니다 (0-100).
     */
    public static evaluate(data: string): number {
        if (!data) return 0;
        let score = 0;
        
        // 1. 길이 기반 점수 (최대 40점)
        score += Math.min(40, data.length / 50);
        
        // 2. 구조화 기반 점수 (최대 30점)
        if (data.includes('##') || data.includes('**') || data.includes('- ')) {
            score += 30;
        }
        
        // 3. 밀도/정보량 기반 점수 (최대 30점)
        // 코드 블록이나 구체적 링크가 있으면 가산점
        if (data.includes('```')) score += 15;
        if (data.includes('## 💻 실전 구현') || data.includes('Implementation')) score += 10;
        if (data.includes('[[') || data.includes('http')) score += 5;
        
        // 감점 요소: Placeholder 나 Empty 상태
        if (data.includes('[Placeholder]') || data.includes('TODO')) {
            score -= 20;
        }

        
        return Math.max(0, Math.min(100, score));
    }
}

export class PerformanceProfiler {
    /**
     * LLM 호출 시 발생하는 비동기 오버헤드와 생성 시간을 측정합니다.
     * 이 지표를 통해 병목(Bottleneck) 현상을 정밀하게 추적할 수 있습니다.
     */
    public static logLLMLatency(agentName: string, durationMs: number, outputLength: number): void {
        // 영어권 기준 대략적인 토큰 수 산정 (1 token ≈ 4 characters)
        const tokensApprox = Math.floor(outputLength / 4);
        const tokensPerSecond = durationMs > 0 ? tokensApprox / (durationMs / 1000) : 0;
        
        logInfo(
            `[Profiler] [${agentName}] LLM Latency: ${durationMs}ms | ` +
            `Output: ${outputLength} chars (~${tokensApprox} tokens) | ` +
            `Speed: ${tokensPerSecond.toFixed(2)} tok/s`
        );
    }
}

export class ConflictDetector {
    /**
     * [Astra v4.1] 도메인 맥락 기반의 의미적 괴리(Semantic Divergence)를 분석합니다.
     * 데이터 내의 논리적 모순이나 상충하는 지표를 탐지하여 위험도를 산출합니다.
     */
    public static analyzeSemanticDivergence(data: string): number {
        if (!data) return 0;
        let riskScore = 0;

        // 1. 수치적 모순 탐지 (Metric Contradiction)
        // 동일 문맥 내에서 서로 다른 수치가 발견되는 패턴 탐지
        const metricPatterns = [
            /(\d+%)\s+vs\s+(\d+%)/g,
            /(\d+ms)\s+대비\s+(\d+ms)/g,
            /상충되는\s+(데이터|정보|결과)/i
        ];
        
        for (const pattern of metricPatterns) {
            if (pattern.test(data)) riskScore += 25;
        }

        // 2. 논리적 상충 용어 탐지 (Logical Divergence)
        const conflictTerms = [
            ['최적화', '성능 저하'],
            ['안정적', '불안정'],
            ['증가', '감소'],
            ['승인', '반려/경고'],
            ['임상 등급', '비승인/소비자용']
        ];

        for (const [pos, neg] of conflictTerms) {
            if (data.includes(pos) && data.includes(neg)) {
                const posIdx = data.indexOf(pos);
                const negIdx = data.indexOf(neg);
                if (Math.abs(posIdx - negIdx) < 400) {
                    riskScore += 15;
                }
            }
        }

        // 3. 기술적 상충 (Technical Divergence)
        const technicalConflicts = [
            /동기(식)?.*비동기(식)?/g,
            /로컬.*클라우드/g,
            /정적.*동적/g,
            /Success.*Fail/i
        ];
        for (const pattern of technicalConflicts) {
            if (pattern.test(data)) riskScore += 10;
        }

        // 4. 명시적 경고 태그 확인
        if (data.includes('[CONFLICT WARNING]') || data.includes('[ERROR]')) riskScore += 30;

        return Math.min(100, riskScore);
    }
}

export class CognitionAudit {
    /**
     * [Astra v4.0] 지능적 판단 및 정책 준수 여부를 감사(Audit)합니다.
     * 시스템이 얼마나 '생각'하고 '경고'했는지 정량적으로 측정합니다.
     */
    public static auditPolicyCompliance(stage: string, content: string): void {
        const findings = [];
        
        // 1. 충돌 경고 감지 (Conflict Warning)
        if (content.includes('[CONFLICT WARNING]')) {
            findings.push('Conflict Detected & Warning Issued');
        }
        
        // 2. 선제적 제안 감지 (Proactive Advice)
        if (content.includes('## 💡 Astra의 선제적 제안')) {
            findings.push('Proactive Advice Generated');
        }
        
        // 3. 신뢰도 인용 패턴 확인 (Credibility Usage)
        const highTrustCitationCount = (content.match(/\[\[/g) || []).length;
        if (highTrustCitationCount > 0) {
            findings.push(`Knowledge Density: ${highTrustCitationCount} connections used`);
        }

        if (findings.length > 0) {
            logInfo(`[CognitionAudit] [${stage}] ${findings.join(' | ')}`);
        }
    }
}
