/**
 * Chain-of-Verification (CoVe) — [VERIFICATION CHECKLIST] 시스템 프롬프트 블록 생성.
 *
 * 배경: 사용자 피드백 "추론 결과가 나오기 직전, 이 결론이 확보된 지식(제2뇌)에만
 * 근거하고 있는가? 를 스스로 질문하고 검증하는 로직" — 할루시네이션 방지 + 그라운딩
 * 명확화.
 *
 * 원논문 CoVe 는 2-pass (draft → verify → revise). 하지만 ASTRA 는 local-first 라
 * 추가 LLM 호출 비용이 크고, 같은 모델이 self-verify 하는 효과도 제한적. 그래서
 * v1 은 *instructional* CoVe — 시스템 프롬프트에 명시적 검증 체크리스트를 주입해
 * 모델이 한 패스 안에서 "답변 작성 전" 그라운딩 점검을 *내재화* 하도록.
 *
 * 향후 strict 모드에서 두 번째 verification pass 추가 가능 (config knob 준비).
 *
 * Conflict Surface 와의 관계: [CONFLICT WARNINGS] 가 "충돌 출처 데이터" 제공,
 * 이 CoVe 블록이 "그 데이터를 어떻게 verify 할지" 지시. 둘은 서로 보완.
 */

import { RetrievalChunk } from './types';

export interface CoveBlockOptions {
    /** 체크리스트에 나열할 최상위 출처 수. 기본 5. */
    topSourcesCount: number;
    /**
     * Strict 모드 — 켜면 LLM 에게 *모든 주장에 출처 ID 를 inline 으로 인용*하라고 지시.
     * 끄면 일반 가이드만. 기본 off (자연스러운 답변 유지).
     */
    strictMode: boolean;
    /** 출처 미리보기 길이. 기본 140 chars. */
    excerptLength: number;
    /** 사용자 query 일부를 체크리스트에 echo 할지. 기본 true — 모델이 vague answer 방지. */
    echoQuery: boolean;
    /** Query echo 최대 길이. 기본 180. */
    queryEchoMaxLength: number;
}

const DEFAULT_OPTIONS: CoveBlockOptions = {
    topSourcesCount: 5,
    strictMode: false,
    excerptLength: 140,
    echoQuery: true,
    queryEchoMaxLength: 180,
};

function shortExcerpt(text: string, n: number): string {
    if (!text) return '';
    const cleaned = text.replace(/\s+/g, ' ').trim();
    return cleaned.length <= n ? cleaned : cleaned.slice(0, n) + '…';
}

/**
 * CoVe 블록 생성. 검색된 chunks 가 없으면 빈 문자열 — 그라운딩할 출처가 없는 상태에서
 * CoVe 를 강요하면 모델이 "출처 없음" 으로 답변 거부할 수 있음. 단, 사용자 query 가
 * 사실 검증 류일 때만 의미가 있으므로 호출자가 enable/disable 결정 가능.
 */
export function buildCoveChecklistBlock(
    chunks: RetrievalChunk[],
    userPrompt: string,
    options: Partial<CoveBlockOptions> = {},
): string {
    const opts: CoveBlockOptions = { ...DEFAULT_OPTIONS, ...options };
    if (!chunks || chunks.length === 0) return '';

    // 점수 순 상위 N — 다양한 source 가 섞이도록 source 별로 1개씩 round-robin 도 고려했으나,
    // CoVe 는 *근거 강한 출처* 가 더 중요해서 score 단순 정렬 채택.
    const top = chunks
        .filter((c) => c.source !== 'brain-trace') // brain-trace 는 trace 표시용, 본문 없음
        .sort((a, b) => b.score - a.score)
        .slice(0, opts.topSourcesCount);

    if (top.length === 0) return '';

    const lines: string[] = [];
    lines.push('[VERIFICATION CHECKLIST — Chain-of-Verification]');
    lines.push('답변을 *작성하기 전* 다음을 점검. 검증 통과한 주장만 답변에 포함할 것.');

    if (opts.echoQuery && userPrompt && userPrompt.trim()) {
        const q = userPrompt.replace(/\s+/g, ' ').trim();
        const echo = q.length > opts.queryEchoMaxLength ? q.slice(0, opts.queryEchoMaxLength) + '…' : q;
        lines.push('');
        lines.push(`> **사용자 질의**: ${echo}`);
    }

    // ─── Section 1: 근거 매핑 ───
    lines.push('');
    lines.push('## 1. 근거 매핑 (Grounding Inventory)');
    lines.push('이 답변의 핵심 주장 각각이 *어느 출처* 에서 왔는지 명시 가능한가?');
    lines.push('');
    for (let i = 0; i < top.length; i++) {
        const c = top[i];
        const scoreFmt = c.score.toFixed(2);
        const sev = c.metadata?.conflictSeverity && c.metadata.conflictSeverity !== 'NONE'
            ? ` ⚠️${c.metadata.conflictSeverity}` : '';
        lines.push(`- **[S${i + 1}]** \`${c.source}\` · ${c.title || '(제목 없음)'} _(score ${scoreFmt})_${sev}`);
        lines.push(`  > ${shortExcerpt(c.content, opts.excerptLength)}`);
    }
    lines.push('');
    lines.push('출처 미매핑(=어느 S 도 직접 지지하지 않음) 주장은 *모델 일반 지식*. 그 사실을 답변에 명시.');

    // ─── Section 2: 자기 질문 ───
    lines.push('');
    lines.push('## 2. 답변 직전 자기 질문 (Pre-Output Self-Check)');
    lines.push('답변 보내기 전 *반드시* 답하라:');
    lines.push('- (a) 이 답변의 결론이 위 [S1..SN] 중 어디에 직접 근거하나? 매핑 안 되는 결론 = 일반 지식 → 명시.');
    lines.push('- (b) "확실하다", "반드시", "이미 결정됨" 같은 단정적 표현을 쓴다면 출처가 그 강도를 지지하는가? 아니면 톤 완화.');
    lines.push('- (c) 사용자에게 다음 *구체적 액션* 을 제시했는가, 아니면 추상적 조언만 했는가?');
    lines.push('- (d) [CONFLICT WARNINGS] 블록과 결합 — 충돌 출처 사용 시 양측 명시했는가?');

    // ─── Section 3: Strict 모드 (옵션) ───
    if (opts.strictMode) {
        lines.push('');
        lines.push('## 3. ⚙️ STRICT 모드 — Inline Citation 강제');
        lines.push('각 사실 주장 뒤에 `[S1]`, `[S2]` 형식으로 출처 ID 를 *반드시* 인용. 인용 없으면 모델 지식으로 간주되어 답변 신뢰도 감점.');
        lines.push('예) "큐브앤코는 enterprise 요금제다 [S2]." / "일반적으로 SaaS B2B 는 ~ (모델 지식, 직접 출처 없음)."');
    }

    lines.push('');
    lines.push('[/VERIFICATION CHECKLIST]');

    return lines.join('\n');
}
