/**
 * Knowledge Decay — 지식 노후 감쇠 점검 (설계서 10장, "인간처럼 잊어버리는 기능").
 *
 * Self-Evolving OS 마스터 플랜 Phase 4 / Track 4-3. 분야별 반감기로 지식의
 * 신선도 계수를 계산하고, 노후 지식을 보고서로 노출한다.
 *
 * v1 은 *비침습적 감사* — 검색 랭킹은 건드리지 않는다. RAG 평가 하니스로
 * 튜닝된 검색 경로를 측정 없이 바꾸지 않기 위함 (decay 를 랭킹에 반영하려면
 * 골든셋 A/B 로 효과를 증명한 뒤 별도 증분으로). citationTrace 의 Provenance
 * 표시(180일+ 경고)와 상호 보완.
 *
 * 분야 분류는 경로/파일명 키워드 매칭 v1 — 설계서 예시(AI 30일 / SEO 90일 /
 * 트렌드 180일)에 사용자 업무 도메인 규칙을 추가.
 */

export interface DecayRule {
    label: string;
    /** 경로(상대) 또는 파일명에 매치되는 패턴. */
    match: RegExp;
    halfLifeDays: number;
}

/** 위에서 아래로 첫 매치 적용. 마지막은 catch-all. */
export const DEFAULT_DECAY_RULES: DecayRule[] = [
    { label: 'AI/기술', match: /ai|llm|mcp|agent|rag|gpt|claude|gemma|모델|에이전트/iu, halfLifeDays: 30 },
    { label: 'SEO/마케팅', match: /seo|마케팅|상위노출|키워드/iu, halfLifeDays: 90 },
    { label: '시장/트렌드', match: /시장|트렌드|동향|경쟁사|market|trend/iu, halfLifeDays: 180 },
    { label: '회의/프로젝트', match: /회의|meeting|프로젝트|일정/iu, halfLifeDays: 180 },
    { label: '일반', match: /.*/, halfLifeDays: 365 },
];

export type DecayStatus = 'active' | 'aging' | 'stale';

export interface DecayItem {
    relPath: string;
    category: string;
    ageDays: number;
    halfLifeDays: number;
    /** 0.5^(age/halfLife) — 1.0 신선, 0.5 반감, ↓. */
    factor: number;
    status: DecayStatus;
}

export function classifyDecayRule(relPath: string, rules: DecayRule[] = DEFAULT_DECAY_RULES): DecayRule {
    for (const rule of rules) if (rule.match.test(relPath)) return rule;
    return rules[rules.length - 1];
}

export function decayFactor(lastUpdatedMs: number, halfLifeDays: number, nowMs: number): number {
    const ageDays = Math.max(0, (nowMs - lastUpdatedMs) / 86400000);
    return Math.pow(0.5, ageDays / halfLifeDays);
}

/**
 * 파일 목록 → 노후 감사. factor ≥0.5 active(반감기 내), ≥0.25 aging(반감 1~2회),
 * 그 밑 stale(반감 2회+ — 우선 검토 대상).
 */
export function auditKnowledgeDecay(
    files: Array<{ relPath: string; lastUpdated: number }>,
    options: { rules?: DecayRule[]; nowMs?: number } = {},
): DecayItem[] {
    const rules = options.rules ?? DEFAULT_DECAY_RULES;
    const now = options.nowMs ?? Date.now();
    const items: DecayItem[] = files.map((f) => {
        const rule = classifyDecayRule(f.relPath, rules);
        const factor = decayFactor(f.lastUpdated, rule.halfLifeDays, now);
        const ageDays = Math.max(0, (now - f.lastUpdated) / 86400000);
        const status: DecayStatus = factor >= 0.5 ? 'active' : factor >= 0.25 ? 'aging' : 'stale';
        return {
            relPath: f.relPath,
            category: rule.label,
            ageDays: Math.round(ageDays),
            halfLifeDays: rule.halfLifeDays,
            factor,
            status,
        };
    });
    // stale 우선(낮은 factor 순) — 보고서 상단이 가장 급한 검토 대상.
    return items.sort((a, b) => a.factor - b.factor);
}

export function formatDecayReport(items: DecayItem[], meta: { brainName: string; dateStr: string }): string {
    const lines: string[] = [];
    lines.push('# 지식 노후 점검 (Knowledge Decay)');
    lines.push('');
    lines.push(`- 두뇌: ${meta.brainName} · 일시: ${meta.dateStr}`);
    lines.push('- 분야별 반감기: AI/기술 30일 · SEO 90일 · 시장/트렌드·회의 180일 · 일반 365일');
    lines.push('');
    const counts = { active: 0, aging: 0, stale: 0 } as Record<DecayStatus, number>;
    for (const it of items) counts[it.status]++;
    lines.push(`## 요약 — 신선 ${counts.active} · 노화 중 ${counts.aging} · **노후 ${counts.stale}**`);
    lines.push('');
    const stale = items.filter((i) => i.status === 'stale').slice(0, 50);
    if (stale.length === 0) {
        lines.push('노후(stale) 지식 없음.');
    } else {
        lines.push('## 노후 지식 — 갱신/보관/폐기 검토 대상 (factor 낮은 순, 최대 50)');
        lines.push('');
        lines.push('| 파일 | 분야 | 경과일 | 반감기 | factor |');
        lines.push('|---|---|---|---|---|');
        for (const it of stale) {
            lines.push(`| ${it.relPath} | ${it.category} | ${it.ageDays} | ${it.halfLifeDays} | ${it.factor.toFixed(2)} |`);
        }
        lines.push('');
        lines.push('> 처리 권고: 여전히 유효하면 파일을 한 번 갱신(저장)해 신선도를 리셋, 낡았으면 보관 폴더로 이동 또는 삭제.');
        lines.push('> v1 은 보고만 한다 — 자동 이동/삭제 없음 (Human Override 원칙).');
    }
    lines.push('');
    return lines.join('\n');
}
