import chalk from "chalk";
import { MODEL_CONFIGS, TOKENIZER_OPTIONS, DEFAULT_SYSTEM_PROMPT, buildPrompt, readFiles, getFileTokenStats, printFileTokenStats, } from "../oracle.js";
import { isKnownModel } from "../oracle/modelResolver.js";
import { assembleBrowserPrompt } from "../browser/prompt.js";
import { buildTokenEstimateSuffix, formatAttachmentLabel } from "../browser/promptSummary.js";
import { buildCookiePlan } from "../browser/policies.js";
import { describeBrowserControlPlan, formatBrowserControlPlan } from "../browser/controlPlan.js";
import { formatBrowserModelTarget } from "../browser/modelDisplay.js";
export async function runDryRunSummary({ engine, runOptions, cwd, version, log, browserConfig, }, deps = {}) {
    if (engine === "browser") {
        await runBrowserDryRun({ runOptions, cwd, version, log, browserConfig }, deps);
        return;
    }
    await runApiDryRun({ runOptions, cwd, version, log }, deps);
}
async function runApiDryRun({ runOptions, cwd, version, log, }, deps) {
    const readFilesImpl = deps.readFilesImpl ?? readFiles;
    const files = await readFilesImpl(runOptions.file ?? [], { cwd });
    const systemPrompt = runOptions.system?.trim() || DEFAULT_SYSTEM_PROMPT;
    const combinedPrompt = buildPrompt(runOptions.prompt ?? "", files, cwd);
    const modelConfig = isKnownModel(runOptions.model)
        ? MODEL_CONFIGS[runOptions.model]
        : MODEL_CONFIGS["gpt-5.1"];
    const tokenizer = modelConfig.tokenizer;
    const estimatedInputTokens = tokenizer([
        { role: "system", content: systemPrompt },
        { role: "user", content: combinedPrompt },
    ], TOKENIZER_OPTIONS);
    const headerLine = `[dry-run] Oracle (${version}) would call ${runOptions.model} with ~${estimatedInputTokens.toLocaleString()} tokens and ${files.length} files.`;
    log(chalk.cyan(headerLine));
    if (files.length === 0) {
        log(chalk.dim("[dry-run] No files matched the provided --file patterns."));
        return;
    }
    const inputBudget = runOptions.maxInput ?? modelConfig.inputLimit;
    const stats = getFileTokenStats(files, {
        cwd,
        tokenizer,
        tokenizerOptions: TOKENIZER_OPTIONS,
        inputTokenBudget: inputBudget,
    });
    printFileTokenStats(stats, { inputTokenBudget: inputBudget, log });
}
async function runBrowserDryRun({ runOptions, cwd, version, log, browserConfig, }, deps) {
    validateBrowserFollowUps(runOptions, browserConfig);
    const assemblePromptImpl = deps.assembleBrowserPromptImpl ?? assembleBrowserPrompt;
    const artifacts = await assemblePromptImpl(runOptions, { cwd });
    const suffix = buildTokenEstimateSuffix(artifacts);
    const displayModel = formatBrowserModelTarget({
        model: runOptions.model,
        desiredModel: browserConfig?.desiredModel,
        modelStrategy: browserConfig?.modelStrategy,
    });
    const headerLine = `[dry-run] Oracle (${version}) would launch browser mode (${displayModel}) with ~${artifacts.estimatedInputTokens.toLocaleString()} tokens${suffix}.`;
    log(chalk.cyan(headerLine));
    logBrowserControlPlan(browserConfig, log, "dry-run");
    logBrowserFollowUpSummary(runOptions.browserFollowUps, log, "dry-run");
    logBrowserCookieStrategy(browserConfig, log, "dry-run");
    logBrowserArchivePolicy(browserConfig, log, "dry-run");
    logBrowserFileSummary(artifacts, log, "dry-run");
}
function logBrowserControlPlan(browserConfig, log, label) {
    const plan = describeBrowserControlPlan(browserConfig);
    for (const line of formatBrowserControlPlan(plan, label)) {
        log(chalk.dim(line));
    }
}
function logBrowserCookieStrategy(browserConfig, log, label) {
    if (!browserConfig)
        return;
    const plan = buildCookiePlan(browserConfig);
    log(chalk.bold(`[${label}] ${plan.description}`));
}
function logBrowserArchivePolicy(browserConfig, log, label) {
    const mode = browserConfig?.archiveConversations ?? "auto";
    log(chalk.dim(`[${label}] ChatGPT archive policy: ${mode}.`));
}
function logBrowserFileSummary(artifacts, log, label) {
    if (artifacts.attachments.length > 0) {
        const prefix = artifacts.bundled
            ? `[${label}] Bundled upload:`
            : `[${label}] Attachments to upload:`;
        log(chalk.bold(prefix));
        artifacts.attachments.forEach((attachment) => {
            log(`  • ${formatAttachmentLabel(attachment)}`);
        });
        if (artifacts.bundled) {
            log(chalk.dim(`  (bundled ${artifacts.bundled.originalCount} files into ${artifacts.bundled.bundlePath})`));
        }
        return;
    }
    if (artifacts.inlineFileCount > 0) {
        log(chalk.bold(`[${label}] Inline file content:`));
        log(`  • ${artifacts.inlineFileCount} file${artifacts.inlineFileCount === 1 ? "" : "s"} pasted directly into the composer.`);
        return;
    }
    log(chalk.dim(`[${label}] No files attached.`));
}
export async function runBrowserPreview({ runOptions, cwd, version, previewMode, log, browserConfig, }, deps = {}) {
    validateBrowserFollowUps(runOptions, browserConfig);
    const assemblePromptImpl = deps.assembleBrowserPromptImpl ?? assembleBrowserPrompt;
    const artifacts = await assemblePromptImpl(runOptions, { cwd });
    const suffix = buildTokenEstimateSuffix(artifacts);
    const displayModel = formatBrowserModelTarget({
        model: runOptions.model,
        desiredModel: browserConfig?.desiredModel,
        modelStrategy: browserConfig?.modelStrategy,
    });
    const headerLine = `[preview] Oracle (${version}) browser mode (${displayModel}) with ~${artifacts.estimatedInputTokens.toLocaleString()} tokens${suffix}.`;
    log(chalk.cyan(headerLine));
    logBrowserControlPlan(browserConfig, log, "preview");
    logBrowserFollowUpSummary(runOptions.browserFollowUps, log, "preview");
    logBrowserFileSummary(artifacts, log, "preview");
    if (previewMode === "json" || previewMode === "full") {
        const attachmentSummary = artifacts.attachments.map((attachment) => ({
            path: attachment.path,
            displayPath: attachment.displayPath,
            sizeBytes: attachment.sizeBytes,
        }));
        const previewPayload = {
            model: runOptions.model,
            engine: "browser",
            composerText: artifacts.composerText,
            attachments: attachmentSummary,
            inlineFileCount: artifacts.inlineFileCount,
            bundled: artifacts.bundled,
            tokenEstimate: artifacts.estimatedInputTokens,
            browserFollowUps: runOptions.browserFollowUps ?? [],
        };
        log("");
        log(chalk.bold("Preview JSON"));
        log(JSON.stringify(previewPayload, null, 2));
    }
    if (previewMode === "full") {
        log("");
        log(chalk.bold("Composer Text"));
        log(artifacts.composerText || chalk.dim("(empty prompt)"));
    }
}
function logBrowserFollowUpSummary(followUps, log, label) {
    const count = followUps?.filter((entry) => entry.trim().length > 0).length ?? 0;
    if (count > 0) {
        log(chalk.bold(`[${label}] Browser follow-ups: ${count} additional prompt(s).`));
        log(chalk.dim(`[${label}] Multi-turn is explicit only: Oracle will send these prompts in order, but it never invents follow-ups automatically.`));
    }
}
function validateBrowserFollowUps(runOptions, browserConfig) {
    const followUpCount = runOptions.browserFollowUps?.filter((entry) => entry.trim().length > 0).length ?? 0;
    if (followUpCount > 0 && browserConfig?.researchMode === "deep") {
        throw new Error("Browser follow-ups are not supported with Deep Research mode. Put the full research plan into the initial prompt or run a normal browser consult for multi-turn review.");
    }
}
