import * as vscode from 'vscode';
import { findBrainFiles, getActiveBrainProfile, logError } from '../../utils';
import { getConfig } from '../../config';
import { AgentWorkflowManager } from '../../agents/AgentWorkflowManager';
import { ErrorTranslator } from '../../core/errorHandler';
import { StatusBarManager, AgentStatus } from '../../core/statusBar';
import { stripMarkdownFormatting } from '../../core/responseRecovery';
import type { AgentExecutorOptions, ChatMessage } from '../../agent';

export interface WorkflowDeps {
    emitHistoryChanged: () => void;
    chatHistory: ChatMessage[];
    options: AgentExecutorOptions;
    statusBarManager: StatusBarManager;
    getWebview: () => vscode.Webview | undefined;
    getAbortSignal: () => AbortSignal | undefined;
}

export async function executeMultiAgentWorkflow(
    deps: WorkflowDeps,
    prompt: string,
    modelName: string,
    options: any
) {
    if (!deps.getWebview()) return;
    // NOTE: 호출자 (AgentExecutor wrapper) 가 stop() + new AbortController() 를
    // *먼저* 마쳐야 한다 — extracted fn 내부에서 stop 을 부르면 호출자가 막
    // 만든 controller 가 즉시 폐기되기 때문. getAbortSignal() 은 그 새 controller 의
    // signal 을 반환해야 함.
    const signal = deps.getAbortSignal();
    if (!signal) return;

    const webview = deps.getWebview();
    if (!webview) return;

    deps.statusBarManager.updateStatus(AgentStatus.Thinking, 'Multi-Agent Workflow Running');
    webview.postMessage({ type: 'streamStart' });
    deps.options.onStreamLifecycle?.start();

    try {
        let brainContext = 'No specific context available';
        try {
            const config = getConfig();
            const activeBrain = options.brainProfileId
                ? (config.brainProfiles.find((profile) => profile.id === options.brainProfileId) || getActiveBrainProfile())
                : getActiveBrainProfile();
            const brainFiles = findBrainFiles(activeBrain.localBrainPath);
            brainContext = `Brain: ${activeBrain.name}, Files: ${brainFiles.length}`;
        } catch (ctxErr) {
            logError('Failed to load brain context for agents', ctxErr);
        }

        const selectedAgentContext = options.agentSkillContext
            ? `\nSelected Agent Reference:\n${options.agentSkillContext}`
            : '';
        const designerContext = options.designerContext
            ? `\nProject Chronicle Guard:\n${options.designerContext}`
            : '';

        // 워크플로우 매니저에게 설정 기반 실행 위임
        // [Clean Stream] 단계 진행 메시지는 채팅 본문(streamChunk) 이 아닌 사이드바
        // 상단의 workflowStage 인디케이터로만 표시한다 → "생각 단계가 본문에 계속 보임"
        // 답답함 제거. 채팅 버블에는 최종 답변만 한 번에 들어간다.
        const rawFinalReport = await AgentWorkflowManager.runStrictWorkflow(
            prompt,
            modelName,
            `${brainContext}${selectedAgentContext}${designerContext}`,
            signal,
            (step, msg) => {
                deps.getWebview()?.postMessage({
                    type: 'workflowStage',
                    value: { step, message: msg, done: step === '완료' || step === '오류' }
                });
            }
        );

        const wv2 = deps.getWebview();
        if (signal.aborted || !wv2) return;

        // [Plain Text Output] Synthesizer가 잘 따라줬어도 작은 모델은 `##` `**` 를 흘리는 경우가 있어
        // 최종 후처리로 한 번 더 마커를 벗긴다. 채팅 history 에도 정제된 결과만 남겨 다음 턴 컨텍스트에서
        // 마커가 재학습되는 일을 막는다.
        const finalReport = getConfig().outputFormat === 'plain'
            ? stripMarkdownFormatting(rawFinalReport)
            : rawFinalReport;

        wv2.postMessage({ type: 'streamChunk', value: finalReport });
        wv2.postMessage({ type: 'workflowStage', value: { step: '완료', message: '', done: true } });
        wv2.postMessage({ type: 'streamEnd' });

        deps.chatHistory.push({ role: 'assistant', content: finalReport });
        deps.emitHistoryChanged();

        deps.statusBarManager.updateStatus(AgentStatus.Success, 'Workflow Complete');
        wv2.postMessage({ type: 'autoContinue', value: '✅ 모든 분석이 성공적으로 완료되었습니다.' });

    } catch (error: any) {
        // 어떤 종료 경로에서든 stage indicator 는 반드시 닫는다 — 안 닫으면 사이드바에 영원히 "③ 자기 검증..." 가 남는다.
        deps.getWebview()?.postMessage({ type: 'workflowStage', value: { step: '완료', message: '', done: true } });
        if (error.name === 'AbortError' || error.message?.includes('cancelled')) {
            deps.statusBarManager.updateStatus(AgentStatus.Idle, 'Workflow Cancelled');
            return;
        }
        const friendly = ErrorTranslator.translate(error);
        logError('Workflow failed', error);

        const wvErr = deps.getWebview();
        wvErr?.postMessage({ type: 'autoContinue', value: '' });
        wvErr?.postMessage({
            type: 'error',
            value: `### ${friendly.title}\n\n**상태:** ${friendly.message}\n\n**해결 방법:** ${friendly.action}`
        });
        deps.statusBarManager.updateStatus(AgentStatus.Idle, 'Error occurred');
    } finally {
        deps.options.onStreamLifecycle?.end();
    }
}
