/**
 * ASTRA 기능 인벤토리 자동 생성 — 자기 지식 구식화의 근본 수정.
 *
 * 문제 (반복 발생한 심각 버그): ASTRA 의 자기 지식이 *사람이 쓴 스냅샷*
 * (selfIdentity 블록, "ASTRA 자기 아키텍처" 위키 문서)에 의존했다. 스냅샷은
 * 작성 시점에 박제되므로 릴리스마다 구식이 되고, ASTRA 는 자기 평가·개선 제안에서
 * 이미 있는 기능을 "신규 제안"하거나(자가검증 구식 정보 사용) 없는 기능을 주장한다.
 *
 * 수정: 소스 오브 트루스(package.json 의 contributes.commands / configuration +
 * POST_ANSWER_HOOKS 레지스트리)에서 인벤토리 문서를 **활성화 시점에 기계 생성**해
 * 두뇌에 쓴다. 버전이 바뀌면 자동 재생성 — 사람이 갱신을 잊을 수 없는 구조.
 * RAG 가 이 문서를 검색하므로 자기 기능 질문·자기 개선 제안의 근거가 항상 현행이다.
 */
import * as fs from 'fs';
import * as path from 'path';
import * as vscode from 'vscode';
import { getActiveBrainProfile, logError, logInfo } from '../utils';
import { POST_ANSWER_HOOKS } from '../agent/postAnswerHooks';

export const INVENTORY_FILE = 'ASTRA 기능 인벤토리.md';
const STATE_KEY = 'astra.inventoryVersion';

/** 답변 후 훅 id → 한 줄 설명. 레지스트리에 새 훅이 추가되면 id 는 자동 노출되고
 *  설명만 여기 한 줄 추가 (설명 누락 시에도 id 는 문서에 나타난다 — 침묵 누락 방지). */
const HOOK_DESCRIPTIONS: Record<string, string> = {
    'devil-rebuttal': 'Devil Agent 반박 카드 (활성화 시)',
    'self-check': '답변 검증 LLM 호출 — 검색 근거 대조 (opt-in)',
    'term-validator': '글로서리 금지 용어 결정론적 검사',
    'requirement-coverage': '업무 필수 요소 커버리지 결정론적 검사',
    'confidence-escalation': '확신도 산출 + 인간 검토 에스컬레이션 + Reflection 기록',
    'critic-loop': '문제 신호(요소 누락/저확신/근거 약함+단정) 턴만 Critic LLM 검수 1회',
};

/**
 * 학술/일반 개념 명칭 ↔ ASTRA 구현 매핑 — featureConceptMap.ts 로 이전 (순수
 * 모듈). 인벤토리 마크다운과 inventory-cross-check 훅(결정론적 재구현 제안
 * 감지)이 같은 정본을 공유한다.
 */
import { CONCEPT_ENTRIES } from './featureConceptMap';

const CONCEPT_MAP: Array<[concept: string, impl: string]> =
    CONCEPT_ENTRIES.map((e) => [e.concept, e.impl]);

function stripMd(s: string): string {
    return (s || '').replace(/\*\*|`|\[|\]/g, '').replace(/\s+/g, ' ').trim();
}

/** package.json contributes 에서 인벤토리 마크다운 생성 (순수 — 테스트 가능). */
export function buildInventoryMarkdown(pkg: any, nowIso: string): string {
    const version = String(pkg?.version || '?');
    const commands: Array<{ command: string; title: string }> = pkg?.contributes?.commands || [];
    const configProps: Record<string, any> = pkg?.contributes?.configuration?.properties || {};

    const lines: string[] = [
        '---',
        'type: reference',
        'title: "ASTRA 기능 인벤토리 (자동 생성)"',
        `version: "${version}"`,
        `generated_at: ${nowIso}`,
        'aliases: ["ASTRA 기능 목록", "ASTRA 명령어", "내 기능", "ASTRA가 할 수 있는 것", "기능 인벤토리", "ASTRA capabilities"]',
        '---',
        '',
        `# ASTRA 기능 인벤토리 — v${version} (자동 생성)`,
        '',
        '> ⚙️ 이 문서는 Astra 활성화 시 **소스 코드(package.json)에서 기계 생성**됩니다 — 수동 편집 금지 (버전 변경 시 덮어씀).',
        '> 자기 기능에 대한 질문·자기 개선 제안은 이 문서가 **항상 현행** 근거입니다. 서사적 설명은 [[ASTRA 자기 아키텍처]] 참고.',
        '',
        `## 사용자 명령 (${commands.length}개)`,
        ...commands.map(c => `- ${stripMd(c.title)}`),
        '',
        `## 설정으로 제어되는 동작·자동화 (${Object.keys(configProps).length}개)`,
        ...Object.entries(configProps).map(([key, prop]: [string, any]) => {
            const desc = stripMd(String(prop?.markdownDescription || prop?.description || ''));
            const first = desc.split(/(?<=[.다음])\s/)[0] || desc;
            return `- \`${key.replace('g1nation.', '')}\` — ${first.slice(0, 160)}`;
        }),
        '',
        `## 답변 후 자동 검증 훅 (${POST_ANSWER_HOOKS.length}단계 — 매 답변 후 실행)`,
        ...POST_ANSWER_HOOKS.map(h => `- \`${h.id}\` — ${HOOK_DESCRIPTIONS[h.id] || '(설명 미등록 — 코드 참조)'}`),
        '',
        '## ⚠️ 개선 제안 전 필독 — 학술 개념 ↔ 구현 매핑',
        '아래 개념들은 명칭이 달라도 **이미 구현되어 있다**. 이들을 "도입/추가하라"고 제안하면 오답이다:',
        ...CONCEPT_MAP.map(([concept, impl]) => `- **${concept}**: ${impl}`),
        '',
        '## 📖 학습 메커니즘 — 정본 (자기 학습 방식 질문에는 이 섹션만 근거로 답할 것)',
        '',
        '**대원칙: 모델 가중치는 절대 학습되지 않는다.** 모든 "학습"은 두뇌 폴더',
        '(설정된 localBrainPath — ConnectAI 프로젝트 루트가 아님)에 *파일로* 쌓이고,',
        '다음 턴의 검색·프롬프트 주입을 통해 행동이 바뀌는 **외부 기억 기반** 방식이다.',
        '두뇌 폴더를 지우면 학습도 사라진다. "패턴을 학습해 선제적으로 제시한다" 류의',
        '서술은 거짓이다 — 선제 제시 엔진은 존재하지 않는다.',
        '',
        '자동 학습 회로는 정확히 다음 5가지뿐이다:',
        '1. **Correction Loop** — 사용자 정정 발화 감지 → 오류 유형 자동 분류 → 레슨 + 회귀 케이스(.astra/eval/corrections.jsonl) 저장',
        '2. **레슨(Experience Memory)** — 과거 실수가 "실패 방지 체크리스트"로 다음 턴 프롬프트에 주입 (truncation 보호 구역)',
        '3. **약점 프로필** — 최근 정정 통계가 자기검토 블록을 통해 다음 턴 행동을 직접 변경',
        '4. **Alignment Knowledge** — 1인 기업 모드 질문에 사용자가 답해준 내용을 두뇌 "Alignment Knowledge" 폴더에 저장 → 같은 질문 재발 방지',
        '5. **주간 성장 사이클** — decay 리포트(지식 노후), 골든셋 회귀 평가, 학습 큐 갱신',
        '',
        '보조 기억(학습이 아닌 *기억*): 단기 대화 히스토리, [PRIOR TURN CONCLUSION] 앵커,',
        '세션 요약(중기), 두뇌 RAG(장기), Project Chronicle(기록 생성 — 검색 두뇌와 별개).',
        '',
    ];
    return lines.join('\n');
}

/**
 * 버전이 바뀌었거나 문서가 없으면 두뇌에 인벤토리를 재생성. 활성화 시 1회 호출
 * (fire-and-forget — 실패해도 turn 에 영향 없음).
 */
export async function ensureFeatureInventory(context: vscode.ExtensionContext): Promise<void> {
    try {
        const brain = getActiveBrainProfile();
        if (!brain?.localBrainPath || !fs.existsSync(brain.localBrainPath)) return;
        const pkg = vscode.extensions.getExtension('g1nation.astra')?.packageJSON;
        if (!pkg) return;
        const version = String(pkg.version || '?');
        const file = path.join(brain.localBrainPath, INVENTORY_FILE);
        if (context.globalState.get<string>(STATE_KEY) === version && fs.existsSync(file)) return;

        fs.writeFileSync(file, buildInventoryMarkdown(pkg, new Date().toISOString()), 'utf8');
        await context.globalState.update(STATE_KEY, version);
        logInfo('기능 인벤토리 재생성.', { version, file });
    } catch (e: any) {
        logError('기능 인벤토리 생성 실패 (무시).', { error: e?.message ?? String(e) });
    }
}
