/**
 * ============================================================
 * 위키 문서 포맷 — 단일 정본 모듈 (v2.2.278)
 *
 * 배경: 위키 문서를 만드는 기능이 늘 때마다(/wikify → /meet → /email → …)
 * 포맷이 하나씩 새로 생기는 파편화가 진행됐다. 이 모듈이 그 흐름을 끊는다 —
 * **앞으로 위키 문서를 만드는 모든 기능은 여기만 쓴다.**
 *
 * 2층 구조:
 *   ① 봉투(frontmatter) 통일 — `ensureFrontmatter()`
 *      저장되는 모든 문서에 정본 frontmatter 를 보장한다. LLM 이 정본 규격으로
 *      이미 생성한 문서(--- 시작)는 건드리지 않고, 보고서형 문서(/meet 회의록,
 *      /benchmark, /review, /youtube)에는 결정론 봉투를 씌운다.
 *      → wikiSave.persistWikiDoc 이 저장 직전 자동 호출 — 호출자는 신경 쓸 것 없음.
 *   ② 지식 문서 프롬프트 공용 빌더 — `buildKnowledgeWikiPrompt()`
 *      P-Reinforce 정본 템플릿(frontmatter+섹션)에 소스 종류별 특수 규칙만
 *      데이터로 주입한다. 새 소스 추가 = KnowledgeSource 하나 정의가 전부.
 *
 * 정본 템플릿은 Datacollect 브리지 wiki_format.mjs (getCanonicalFormat 이
 * 10분 캐시로 fetch, 실패 시 wikifyPrompt 의 내장 사본 fallback).
 * ============================================================
 */

import { bridgeFetch, BRIDGE_API } from './bridgeClient';
import type { CanonicalWikiFormat } from './prompts/wikifyPrompt';

// ── 정본 템플릿 fetch (일원화 + 캐시) ────────────────────────────────────────
let _canonicalCache: { fmt: CanonicalWikiFormat | null; at: number } | undefined;
const CANONICAL_TTL_MS = 10 * 60_000;

/** 브리지의 포맷 정본. 실패 시 null (호출부 빌더가 내장 사본으로 fallback). */
export async function getCanonicalFormat(): Promise<CanonicalWikiFormat | null> {
    if (_canonicalCache && Date.now() - _canonicalCache.at < CANONICAL_TTL_MS) return _canonicalCache.fmt;
    let fmt: CanonicalWikiFormat | null = null;
    try {
        fmt = await bridgeFetch<CanonicalWikiFormat>(BRIDGE_API.wiki.template, { method: 'GET' }, { timeoutMs: 5000 });
        if (!fmt || !fmt.commonRules || !fmt.frontmatter || !fmt.sections) fmt = null;
    } catch { fmt = null; }
    _canonicalCache = { fmt, at: Date.now() };
    return fmt;
}

// ── ① 봉투(frontmatter) 통일 ─────────────────────────────────────────────────

export interface EnvelopeOpts {
    /** 문서 종류 — frontmatter category·tags 로 들어감 (예: 'meeting', 'benchmark', 'review', 'youtube'). */
    docType: string;
    /** raw_sources 항목 (URL·파일명·"email:제목" 등). */
    sources?: string[];
    /** 변경 이력 첫 줄 문구. 생략 시 docType 기반 기본 문구. */
    origin?: string;
}

/** title → frontmatter id 슬러그 (wikifyPrompt 의 규칙과 동일). */
export function slugifyId(title: string, fallback: string): string {
    return (title.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9가-힣-]/g, '').slice(0, 80)) || fallback;
}

/** 문서가 이미 frontmatter(---) 로 시작하는지 — 코드펜스·공백 관대 판정. */
export function hasFrontmatter(content: string): boolean {
    const t = (content || '').trimStart();
    return t.startsWith('---') || t.replace(/^```(?:markdown|md)?\s*/i, '').trimStart().startsWith('---');
}

/**
 * 정본 frontmatter 봉투 보장 — 이미 있으면 원문 그대로, 없으면 결정론 봉투 prepend.
 * 봉투 필드는 정본(wiki_format.mjs v3.1) frontmatter 와 같은 이름을 사용해
 * 다운스트림(brain 인덱스·그래프·신뢰도 소비자)이 문서 종류와 무관하게 동작한다.
 */
export function ensureFrontmatter(title: string, content: string, opts: EnvelopeOpts): string {
    if (hasFrontmatter(content)) return content;
    const today = new Date().toISOString().slice(0, 10);
    const sources = (opts.sources || []).map(s => JSON.stringify(String(s)));
    const fm = [
        '---',
        `id: ${slugifyId(title, opts.docType + '-doc')}`,
        `title: ${JSON.stringify(title)}`,
        `category: ${JSON.stringify(opts.docType)}`,
        'status: "draft"',
        'verification_status: "conceptual"',
        'aliases: []',
        'source_trust_level: "B"',
        'confidence_score: 0.80',
        `created_at: ${today}`,
        `updated_at: ${today}`,
        `tags: ["${opts.docType}", "astra"]`,
        `raw_sources: [${sources.join(', ')}]`,
        '---',
        '',
    ].join('\n');
    return fm + content + `\n\n## 📝 변경 이력 (Change history)\n- ${today}: ${opts.origin || `Astra ${opts.docType} 산출물로 생성.`}\n`;
}

// ── ② 지식 문서 프롬프트 공용 빌더 ───────────────────────────────────────────

/**
 * 지식화(위키화) 대상 소스 기술자 — 새 소스 종류는 이 객체 하나로 추가한다.
 * (예: 슬랙 스레드 지식화를 만들면 kind:'slack' + 특수 규칙 몇 줄이 전부.)
 */
export interface KnowledgeSource {
    /** 소스 종류 라벨 — tags·출처 평가 힌트에 사용. */
    kind: string;
    /** 문서 주제(제목). */
    topic: string;
    /** 근거 원문 (추출 본문·트랜스크립트 등). 빌더가 30,000자 컷. */
    body: string;
    /** [소스 메타] 블록에 표시할 키-값 (URL·참여자·기간 등). */
    meta?: Record<string, string>;
    /** frontmatter tags (kind 는 자동 포함). */
    tags?: string[];
    /** raw_sources / [S1] 표기 값 (예: URL, "email:제목"). */
    sourceRef: string;
    /** 소스 종류별 특수 규칙 (번호는 빌더가 5번부터 이어붙임). */
    extraRules?: string[];
    /** source_trust_level 평가 힌트 한 줄. */
    trustHint?: string;
    /** 변경 이력 문구. */
    origin?: string;
}

/** 정본 골격 placeholder 치환 (wikifyPrompt.fill 과 동일 규칙). */
function fill(tpl: string, vars: Record<string, string>): string {
    return tpl.replace(/\{\{(\w+)\}\}/g, (_, k) => vars[k] ?? '');
}

/**
 * P-Reinforce 정본 지식 문서 프롬프트 — 모든 지식화 기능의 단일 진입점.
 * canonical 미제공(null) 시 wikifyPrompt 내장 사본 사용.
 */
export function buildKnowledgeWikiPrompt(src: KnowledgeSource, canonical?: CanonicalWikiFormat | null): string {
    // 내장 사본은 wikifyPrompt 가 소유 — 순환 없이 lazy require.
    const { EMBEDDED_FALLBACK } = require('./prompts/wikifyPrompt') as { EMBEDDED_FALLBACK: CanonicalWikiFormat };
    const fmt = canonical && canonical.commonRules && canonical.frontmatter && canonical.sections
        ? canonical : EMBEDDED_FALLBACK;

    const today = new Date().toISOString().slice(0, 10);
    const topic = (src.topic || `${src.kind} 지식`).trim();
    const tags = [...new Set([src.kind, ...(src.tags || [])])].map(t => `"${t}"`).join(', ');
    const vars = {
        ID: slugifyId(topic, `${src.kind}-wiki`), TITLE: topic, TOPIC: topic, ROOT: topic, TODAY: today,
        TAGS: tags, SOURCES: `[${JSON.stringify(src.sourceRef)}]`,
        ORIGIN: src.origin || `Astra ${src.kind} 지식화로 초안 생성.`,
    };

    const baseRules = [
        `1. 반드시 아래 [소스 본문]의 내용만을 근거로 작성하시오. 외부 지식을 절대 섞지 마시오.`,
        `2. 반드시 아래 Markdown 템플릿과 Frontmatter 형식을 정확히 따르시오. 섹션 이름과 구조를 변경하지 마시오.`,
        `3. 본문에 없는 정보는 지어내지 말고, 해당 섹션에 "소스에서 확인되지 않음"이라고 명시하시오. 수치·날짜·금액·고유명사는 원문 그대로 보존하시오.`,
        `4. 한국어로 작성하시오. 관련 개념·고유명사는 [[대괄호 두 개]]로 감싸 위키 링크로 만드시오. 위키 링크는 반드시 \`[[\` 로 열고 \`]]\` 로 닫으시오.`,
    ];
    const extra = (src.extraRules || []).map((r, i) => `${5 + i}. ${r}`);
    const trustRule = `${5 + extra.length}. 이 문서의 출처는 ${src.kind} 소스 1건이므로 '## 📚 출처'의 [S1]은 ${src.sourceRef} 를 가리키며, source_trust_level 은 ${src.trustHint || '소스 성격에 따라 정직하게'} 평가하시오.`;

    const metaLines = Object.entries(src.meta || {}).map(([k, v]) => `- ${k}: ${v || '(없음)'}`);

    return `임무: 아래 ${src.kind} 소스를 근거로 P-Reinforce v${fmt.version.replace('-embedded', '')} 규격에 맞춰 고밀도 지식 문서를 작성하시오.
주제: '${topic}'

[필수 규칙]
${[...baseRules, ...extra, trustRule].join('\n')}
${fill(fmt.commonRules, vars)}

[소스 메타]
${metaLines.join('\n') || '- (메타 없음)'}

[소스 본문]
\`\`\`
${String(src.body || '').slice(0, 30000)}
\`\`\`

[출력 템플릿 - 이 형식을 정확히 따르시오]

${fill(fmt.frontmatter, vars)}

${fill(fmt.sections, vars)}`;
}
