import { ChunkedWriter, PersonaOverrides } from './factory';
import { AgentEngine, PipelineStage, AgentExecuteOptions } from '../lib/engine';
import { getConfig } from '../config';

/**
 * Multi-agent 워크플로우를 외부에 노출하는 얇은 매니저.
 *
 * 예전엔 planner / researcher / reflector / writer / synthesizer 5개 persona 를
 * 줄세웠지만, 각 hop 마다 컨텍스트가 누적되고 원본 본문이 추상화로 손실돼
 * 사용자가 본문 분석을 요청해도 "분석 방법론" 만 만들어내는 사고가 있었음.
 *
 * 현재 흐름: 단일 ChunkedWriter 가 outline → section[N] → polish 세 역할을
 * 같은 모델에서 번갈아 수행 → 각 호출은 작고(컨텍스트 폭증 없음), 본문은
 * 매 호출에 직접 전달돼 손실 없음.
 */
export class AgentWorkflowManager {
    public static async runStrictWorkflow(
        prompt: string,
        modelName: string,
        brainContext: string,
        signal: AbortSignal,
        onProgress: (step: string, message: string) => void
    ): Promise<string> {
        // 사용자 config 의 polish persona override 가 있으면 ChunkedWriter 에 주입.
        // 비어 있으면 기본 polish persona 사용.
        const cfg = getConfig();
        const overrides: PersonaOverrides | undefined = cfg.polishPersonaOverride
            ? { polish: cfg.polishPersonaOverride }
            : undefined;
        const writer = new ChunkedWriter(modelName, overrides);
        const engine = new AgentEngine(writer);
        const missionId = `mission_${Date.now()}`;

        const runOptions: AgentExecuteOptions = {
            config: { model: modelName },
        };

        try {
            return await engine.runMission(
                missionId,
                prompt,
                brainContext,
                signal,
                (stage: PipelineStage, message: string) => {
                    onProgress(this.mapStageToUI(stage), message);
                },
                runOptions
            );
        } catch (error: any) {
            if (error.name === 'AbortError' || error.message.includes('cancelled')) {
                throw error;
            }
            throw new Error(`[Workflow Manager] ${error.message}`);
        }
    }

    private static mapStageToUI(stage: PipelineStage): string {
        const maps: Record<PipelineStage, string> = {
            idle: '대기',
            outline: '① 구조 잡기',
            section: '② 본문 작성',
            polish: '③ 최종 다듬기',
            direct: '⚡ 즉답',
            completed: '완료',
            error: '오류',
        };
        return maps[stage] || '진행 중';
    }
}
