/**
 * Citation Trace — 답변 *끝* 에 "출처:" 한 줄 명시 지시.
 *
 * CoVe Strict 모드 (v2.2.184) 와 차이:
 *   - CoVe Strict: 모든 사실 주장 뒤에 inline `[S1]` 인용 강제 — verbose, 학술적
 *   - Citation Trace: 답변 끝에 *사용된 출처* 한 줄 정리 — 가벼움, 항상 ON 권장
 *
 * 둘은 함께 동작 가능. CoVe 가 [S1]..[SN] 라벨을 system prompt 에 노출하면,
 * Citation Trace 는 LLM 에게 "그 라벨들 중 답변에 *실제로 사용된* 것을 끝에 한 줄
 * 정리" 라고 지시.
 *
 * 효과: 사용자가 답변 검증 가능 — "이 답변이 어느 출처에 기반했나" 명시.
 * 할루시네이션 억제 — LLM 이 출처 없는 주장 줄임.
 *
 * 비용: 시스템 프롬프트 ~10줄 추가. LLM 출력에 1줄 추가.
 */

import { RetrievalChunk } from './types';

export interface CitationTraceOptions {
    /** 답변 끝 *출처 한 줄* 형식. 'tail' 만 v1 지원. */
    format: 'tail';
    /**
     * Provenance 표시 (Self-Evolving OS Phase 2 / Track 1-4) — 상위 출처의
     * 최종 수정일·score 를 블록에 노출하고, 오래된 출처 사용 시 모델이 답변에
     * 그 사실을 명시하게 지시. 기본 true.
     */
    provenanceEnabled: boolean;
    /** 이 일수보다 오래된 출처는 "오래됨" 으로 분류. 기본 180일. */
    staleAfterDays: number;
    /** Provenance 에 나열할 상위 출처 수. 기본 5. */
    provenanceTopCount: number;
    /** 테스트 주입용 현재 시각 (epoch ms). 기본 Date.now(). */
    nowMs?: number;
}

const DEFAULT_OPTIONS: CitationTraceOptions = {
    format: 'tail',
    provenanceEnabled: true,
    staleAfterDays: 180,
    provenanceTopCount: 5,
};

function fmtDate(epochMs: number): string {
    const d = new Date(epochMs);
    const mm = String(d.getMonth() + 1).padStart(2, '0');
    const dd = String(d.getDate()).padStart(2, '0');
    return `${d.getFullYear()}-${mm}-${dd}`;
}

/**
 * Citation Trace 블록 — chunks 가 *있어야* 의미 있으니 비어 있으면 빈 문자열.
 * Casual conversation 모드는 호출자가 미리 걸러야.
 */
export function buildCitationTraceBlock(
    chunks: RetrievalChunk[],
    options: Partial<CitationTraceOptions> = {},
): string {
    if (!chunks || chunks.length === 0) return '';
    const opts: CitationTraceOptions = { ...DEFAULT_OPTIONS, ...options };

    const lines: string[] = [];
    lines.push('[CITATION TRACE]');
    lines.push('답변에서 *검색된 출처를 사용했다면*, 답변 끝에 다음 형식으로 *한 줄* 정리:');
    lines.push('');
    lines.push('*출처:* `파일명.md` · `chunk-title` · `chunk-title2`');
    lines.push('');
    lines.push('[규칙]');
    lines.push('1. 실제 답변 작성에 *사용한* 출처만 나열. 검색됐지만 안 쓴 출처는 제외.');
    lines.push('2. 출처 라벨은 파일명(있으면) 또는 chunk title 그대로 — 임의 변형 금지.');
    lines.push('3. 일반 모델 지식만 사용했다면: *출처: 모델 지식 (검색 출처 미사용)*');
    lines.push('4. 답변이 검증 가능하도록 — 사용자가 그 파일을 열면 답변 근거를 확인할 수 있어야.');
    lines.push('5. *출처:* 라인은 답변 *맨 끝* 한 번만 — 본문 중간에 흩어 놓지 말 것.');

    // ─── Provenance — 출처 신선도·신뢰도 메타데이터 (Track 1-4) ───
    // 목적: "어떤 지식 때문에 이 결론이 나왔는가" 역추적 + 오래된 지식 기반 답변 표시.
    if (opts.provenanceEnabled) {
        const now = opts.nowMs ?? Date.now();
        const staleMs = opts.staleAfterDays * 24 * 60 * 60 * 1000;
        const top = chunks
            .filter((c) => c.source !== 'brain-trace')
            .sort((a, b) => b.score - a.score)
            .slice(0, opts.provenanceTopCount);
        const withMeta = top.filter((c) => typeof c.metadata?.lastUpdated === 'number');
        if (withMeta.length > 0) {
            lines.push('');
            lines.push('[출처 메타데이터 — Provenance]');
            for (const c of withMeta) {
                const updated = c.metadata.lastUpdated as number;
                const isStale = now - updated > staleMs;
                const staleTag = isStale ? ` ⚠️오래됨(${opts.staleAfterDays}일+)` : '';
                lines.push(`- \`${c.title || '(제목 없음)'}\` — 수정일 ${fmtDate(updated)}, score ${c.score.toFixed(2)}${staleTag}`);
            }
            if (withMeta.some((c) => now - (c.metadata.lastUpdated as number) > staleMs)) {
                lines.push('⚠️오래됨 출처를 핵심 근거로 사용하면 답변에 "출처가 오래되어 현재와 다를 수 있음" 을 명시할 것.');
            }
        }
    }

    lines.push('[/CITATION TRACE]');
    return lines.join('\n');
}
