import * as fs from 'fs';
import { logInfo, logError } from '../../utils';
import { getOrCreateAgentEntry } from '../../skills/agentKnowledgeMap';
import { loadExternalSkills, formatSkillsAsPromptBlock } from '../../skills/externalSkillLoader';

/**
 * Chat turn 직전 *agent skill 컨텍스트* 와 *effective model* 해석. sidebarProvider
 * 의 `_handlePrompt` 안 50줄짜리 if/else 블록을 deps-free 함수로 분리.
 *
 * 흐름:
 *   1) agentFile 비어 있거나 'none' 이거나 디스크에 없으면 → context undefined,
 *      base model 그대로.
 *   2) 파일을 읽고 placeholder 인지 검사 — 사용자가 새로 만들고 아직 내용 안 채운
 *      케이스. placeholder 면 'placeholder' notification + context undefined.
 *   3) 실제 본문이면 그걸 agentSkillContext 로 채우고, agent ↔ knowledge map 에서
 *      external skills 를 가져와 append. Knowledge map entry 가 model 을 pinned 했으면
 *      base 보다 우선시 + 'modelOverride' notification.
 *
 * Webview send 는 provider 가 담당 — 이 함수는 *어떤 알림이 필요한지* 만 결과에
 * 담아 반환 (notifications 배열). provider 가 그걸 보고 적절한 메시지 송신.
 *
 * Stateless — vscode/webview/instance state 의존 없음. fs/logger 만 사용.
 */

export type AgentSkillNotification =
    | { type: 'placeholder' }
    | { type: 'modelOverride'; agent: string; model: string };

export interface AgentSkillResolution {
    /** Agent skill blob — placeholder/없음/실패 시 undefined. */
    agentSkillContext: string | undefined;
    /** Per-agent override 가 있으면 그 모델, 아니면 base model 그대로. */
    effectiveModel: string;
    /** Provider 가 webview 에 송신해야 할 알림들 (placeholder warning / model override 알림). */
    notifications: AgentSkillNotification[];
}

export function resolveAgentSkill(
    agentFile: string | undefined | null,
    baseModel: string,
): AgentSkillResolution {
    const effectiveModel = baseModel || '';
    if (!agentFile || agentFile === 'none' || !fs.existsSync(agentFile)) {
        return { agentSkillContext: undefined, effectiveModel, notifications: [] };
    }

    const fileContent = fs.readFileSync(agentFile, 'utf8');
    // Placeholder guard: "# Agent Persona: …" 헤더 + "Add your instructions here…" 만 있으면
    // 사용자가 아직 본문을 안 채운 freshly-created agent. 그대로 agent prompt 로 쓰면
    // 모델이 "Add your instructions here" 를 instructions 로 잘못 해석.
    const body = fileContent.replace(/^﻿?#\s*Agent\s*Persona\s*:.*$/im, '').trim();
    const isPlaceholder = !body || /^add your instructions here/i.test(body);
    if (isPlaceholder) {
        logInfo('Selected agent has no real instructions — running without agent mode.', { agentFile });
        return {
            agentSkillContext: undefined,
            effectiveModel,
            notifications: [{ type: 'placeholder' }],
        };
    }

    let agentSkillContext: string = fileContent;
    let finalModel = effectiveModel;
    const notifications: AgentSkillNotification[] = [];

    try {
        const entry = getOrCreateAgentEntry(agentFile);
        const bundle = loadExternalSkills(entry.skillFolders);
        const block = formatSkillsAsPromptBlock(bundle);
        if (block) {
            // External skills 를 agent .md 본문 끝에 append — 다음 파이프라인 (agent.ts /
            // agent-mode override) 이 동일 blob 으로 처리해서 추가 분기 불필요.
            agentSkillContext = `${agentSkillContext.trim()}\n\n${block}`;
        }
        const pinned = entry.model?.trim();
        if (pinned && pinned !== finalModel) {
            logInfo('Per-agent model override applied.', {
                agent: entry.name,
                requested: finalModel,
                pinned,
            });
            finalModel = pinned;
            notifications.push({ type: 'modelOverride', agent: entry.name, model: pinned });
        }
    } catch (e: any) {
        logError('External skill load failed.', { error: e?.message || String(e) });
    }

    return { agentSkillContext, effectiveModel: finalModel, notifications };
}
