/**
 * CEO synthesis pass — runs after all specialists have finished.
 *
 * Given the per-agent outputs, this asks the CEO model to produce the final
 * markdown report (✅ 완료 / 🚀 다음 / 💡 인사이트) that the user actually
 * reads. The function deliberately doesn't try to *parse* the response —
 * we trust the prompt to keep the structure and surface the text as-is.
 *
 * Failure mode: when the CEO call errors out we still return whatever raw
 * text we managed to collect (typically empty). The dispatcher then
 * concatenates the per-agent outputs into a fallback report so the user
 * never sees a blank screen.
 */
import { IAIService } from '../../core/services';
import { logError } from '../../utils';
import { resolveAgent } from './companyConfig';
import { applyPromptVars, CEO_REPORT_PROMPT } from './promptAssets';
import { AgentTurnOutput, CompanyState, CompanyTaskPlan } from './types';

/** Max characters of per-agent output to feed back into the CEO synthesis. */
const PER_AGENT_REPORT_BUDGET = 2000;

export interface ReportResult {
    /** Generated markdown. Empty string on hard failure. */
    report: string;
    /** True when the LLM call succeeded with non-empty content. */
    ok: boolean;
}

/**
 * Build the user-message payload the CEO sees: the brief, plus each agent's
 * task + output, lightly trimmed so the planner-model's context window
 * doesn't blow up on a verbose specialist.
 */
function _buildReportUserMessage(
    plan: CompanyTaskPlan,
    outputs: AgentTurnOutput[],
    state: CompanyState,
): string {
    const lines: string[] = [];
    if (plan.brief) {
        lines.push('## 이번 작업 브리프');
        lines.push(plan.brief);
        lines.push('');
    }
    lines.push('## 에이전트별 산출물');
    if (outputs.length === 0) {
        lines.push('_(no agent dispatched this turn — produce a brief acknowledgement instead)_');
    } else {
        for (const out of outputs) {
            const def = resolveAgent(state, out.agentId);
            const head = def ? `### ${def.emoji} ${def.name}` : `### ${out.agentId}`;
            lines.push('');
            lines.push(head);
            lines.push(`**Task:** ${out.task}`);
            if (out.error) {
                lines.push(`**Note:** dispatch failed — \`${out.error}\`. 사용 가능한 부분만 인용해서 보고.`);
            }
            lines.push('');
            const body = out.response.length > PER_AGENT_REPORT_BUDGET
                ? out.response.slice(0, PER_AGENT_REPORT_BUDGET) + '\n…(truncated)'
                : out.response;
            lines.push(body);
        }
    }
    return lines.join('\n');
}

/** Build a fallback report by concatenating agent outputs verbatim. Used when the LLM synthesis fails. */
export function buildFallbackReport(
    plan: CompanyTaskPlan,
    outputs: AgentTurnOutput[],
    state: CompanyState,
): string {
    const parts: string[] = ['## ✅ 완료된 작업'];
    if (outputs.length === 0) {
        parts.push('- _(no agents ran this turn)_');
    } else {
        for (const out of outputs) {
            const def = resolveAgent(state, out.agentId);
            const head = def ? `**${def.emoji} ${def.name}**` : `**${out.agentId}**`;
            const firstLine = (out.response.split(/\n/).find((l) => l.trim()) || out.task).trim();
            parts.push(`- ${head} — ${firstLine.slice(0, 120)}`);
        }
    }
    parts.push('');
    parts.push('## 🚀 다음 액션');
    parts.push('_(CEO 합성 실패 — 위 산출물을 직접 확인하세요)_');
    parts.push('');
    parts.push('## 💡 인사이트');
    parts.push(`- 이번 턴은 ${outputs.length}명의 에이전트가 작업했습니다.`);
    if (plan.brief) parts.push(`- 브리프: ${plan.brief}`);
    return parts.join('\n');
}

/** End-to-end synthesis call. Never throws — returns `{ ok: false, … }` on error. */
export async function runCeoReporter(
    ai: IAIService,
    plan: CompanyTaskPlan,
    outputs: AgentTurnOutput[],
    state: CompanyState,
    options: { model?: string; timeoutMs?: number; signal?: AbortSignal } = {},
): Promise<ReportResult> {
    const system = applyPromptVars(CEO_REPORT_PROMPT, { company: state.companyName });
    const user = _buildReportUserMessage(plan, outputs, state);
    try {
        const result = await ai.chat({
            system,
            user,
            model: options.model,
            timeoutMs: options.timeoutMs,
            signal: options.signal,
        });
        const text = (result.content || '').trim();
        if (!text) {
            return { report: buildFallbackReport(plan, outputs, state), ok: false };
        }
        return { report: text, ok: true };
    } catch (e: any) {
        logError('ceoReporter: AI call failed.', { error: e?.message ?? String(e) });
        return { report: buildFallbackReport(plan, outputs, state), ok: false };
    }
}
