import {
    isProjectKnowledgeCreationRequest,
    buildAstraStanceContext,
} from '../../lib/contextBuilders/localProjectIntent';
import { isThinkingPartnerRequest } from '../../lib/contextBuilders/promptDetection';
import { buildSelfIdentityBlock } from '../../lib/contextBuilders/selfIdentity';
import { buildKnowledgeMixPolicy } from '../../retrieval/knowledgeMix';

export interface BuildAstraModeSystemPromptInput {
    prompt: string | null;
    systemPrompt: string;
    modeBridgeCtx: string;
    /** [PRIOR TURN CONCLUSION] 블록 — 직전 assistant 답변의 첫 문장. follow-up 정정 대응용. */
    priorConclusionCtx: string;
    designerCtx: string;
    projectArchitectureCtx: string;
    secondBrainTraceCtx: string;
    memoryCtx: string;
    knowledgeContextForPrompt: string;
    contextBlock: string;
    negativeCtx: string;
    isCasualConversation: boolean;
    localPathContext: string;
    /** From this._turnCtx.knowledgeMix — pass null when absent. */
    knowledgeMix: any;
    /**
     * 동적 시스템 프롬프트 블록 Map (id → 본문). memoryContext 가 채움.
     * 옛 named param 5개 (conflictWarningsCtx/coveChecklistCtx/intentClarificationCtx/
     * citationTraceCtx/terminologyCtx) 를 통합. casual 모드는 자동 skip.
     * 등록 순서대로 [CONTEXT] *밖* 에 join 되어 주입.
     */
    dynamicBlocks?: Map<string, string>;
}

export function buildAstraModeSystemPrompt(input: BuildAstraModeSystemPromptInput): string {
    const {
        prompt,
        systemPrompt,
        modeBridgeCtx,
        priorConclusionCtx,
        designerCtx,
        projectArchitectureCtx,
        secondBrainTraceCtx,
        memoryCtx,
        knowledgeContextForPrompt,
        contextBlock,
        negativeCtx,
        isCasualConversation,
        localPathContext,
        knowledgeMix,
        dynamicBlocks,
    } = input;

    // 기존 Astra 모드 (에이전트 미선택)
    const localProjectKnowledgeCtx = prompt && localPathContext && isProjectKnowledgeCreationRequest(prompt)
        ? `\n\n[LOCAL PROJECT KNOWLEDGE CREATION OVERRIDE]\nThe user gave an accessible local project path and asked to create project knowledge. Do not ask blocking scope questions. Use a sensible default MVP: create or propose a project overview note from the inspected tree and priority file previews. If writing is not explicitly safe, provide the concrete note draft and target path.`
        : '';
    const thinkingPartnerCtx = prompt && !isCasualConversation && isThinkingPartnerRequest(prompt)
        ? `\n\n[JARVIS THINKING PARTNER MODE]\nThe user is using this tool to clarify project direction, not just to receive generic advice. Give a clear opinionated verdict first. Then separate confirmed facts, inferences, concerns, decision forks, and the next small action. Do not merely say the direction is good. If evidence is thin, say exactly what is missing and what file or record should be checked next.`
        : '';
    const astraStanceCtx = prompt && !isCasualConversation
        ? `\n\n${buildAstraStanceContext(prompt, localPathContext)}`
        : '';
    // The v4 knowledge-management policy only matters when knowledge is actually in play —
    // skip it for greetings/small talk so it doesn't dilute the [CASUAL CONVERSATION MODE] directive.
    const v4PolicyCtx = isCasualConversation ? '' : [
        "\n### 🏛️ 지식 관리 정책 v4.0 (Knowledge Management Policy Applied)",
        "- [신뢰도] '의도적으로 작성된 글'은 Medium 이상의 신뢰도를 부여하여 최우선 근거로 활용할 것.",
        "- [품질] 데이터의 양보다 '추론 기여 밀도'를 중시하여 핵심 위주로 깊이 있게 서술할 것.",
        "- [충돌] 지식 간 충돌 발생 시 시스템이 독단적으로 판단하지 말고, 반드시 [CONFLICT WARNING] 플래그와 함께 상충되는 두 관점을 모두 명시하여 사용자에게 판단을 위임할 것."
    ].join('\n');

    // [자기 지식 + 1인칭] Astra/Agent 양 모드 공용 블록 — 자기 오보고("frozen 모델")와
    // 3인칭 화법("Astra는~") 방지. 본문은 selfIdentity.ts 참조.
    const selfGrowthIdentityCtx = isCasualConversation ? '' : `\n${buildSelfIdentityBlock()}`;

    // [CONTEXT] … [/CONTEXT] 사이만 컨텍스트 초과 시 trim 대상 — negative constraints 는 보호.
    const casualCtx = isCasualConversation
        ? '\n\n[CASUAL CONVERSATION MODE]\nThe user sent a greeting, acknowledgement, or light conversational message. Reply naturally and briefly to the message itself. Do not use Second Brain, memory, project records, reports, references, or analysis unless the user explicitly asks for them.'
        : '';
    // Knowledge Mix policy: tells the model how strongly to lean on Second Brain
    // evidence vs. its own general knowledge for this turn. Suppressed for casual
    // chat — pure greetings don't need to be told anything about RAG balance.
    const knowledgeMixCtx = (!isCasualConversation && knowledgeMix)
        ? (() => {
            const block = buildKnowledgeMixPolicy(knowledgeMix);
            return block ? `\n\n${block}` : '';
        })()
        : '';
    // memoryCtx(RAG/메모리/lessons)는 [CONTEXT] 안에 — 토큰이 빡빡하면 대화 기록보다 먼저 잘림.
    // priorConclusionCtx 는 modeBridgeCtx 와 같은 위치 (base systemPrompt 직후) — 모델이
    // 자기 직전 결론을 anchor 로 잡고 사용자의 follow-up 을 그 결론에 대한 정정으로 해석하게.
    const priorConclusionBlock = priorConclusionCtx ? '\n\n' + priorConclusionCtx : '';
    // 동적 블록 join — [CONTEXT] *밖* 에 주입돼 token-truncation 시 보호. Casual 모드면
    // RAG context 자체를 안 쓰므로 동적 블록도 의미 없음 → 일괄 skip.
    // 등록 순서대로 join (memoryContext 가 메모리 호출 순으로 set — 현재: intent →
    // terminology → conflict → cove → citation). 빈 본문 entry 는 자동 제외.
    let dynamicBlocksJoined = '';
    if (!isCasualConversation && dynamicBlocks && dynamicBlocks.size > 0) {
        for (const body of dynamicBlocks.values()) {
            if (body && body.trim()) dynamicBlocksJoined += '\n\n' + body;
        }
    }
    // [CONTEXT] 내부 순서 = 잘림 우선순위 (truncation 은 body *뒤*부터 자름):
    // contextBlock(사용자가 지금 가리킨 실데이터 — URL 본문/열린 파일/일정)을 맨 앞에
    // 둬 최후까지 보존, 배경 지식(brain RAG)과 memory 는 그보다 먼저 잘리게 한다.
    return `${systemPrompt}${modeBridgeCtx ? '\n\n' + modeBridgeCtx : ''}${priorConclusionBlock}${designerCtx}${projectArchitectureCtx}${localProjectKnowledgeCtx}${thinkingPartnerCtx}${astraStanceCtx}${secondBrainTraceCtx}${v4PolicyCtx}${selfGrowthIdentityCtx}${knowledgeMixCtx}${casualCtx}${dynamicBlocksJoined}\n\n[CONTEXT]\n${contextBlock}\n${knowledgeContextForPrompt}\n${memoryCtx}\n[/CONTEXT]\n${negativeCtx}`;
}
