import { redactPublicDiagnosticText } from "../security/redactionBoundary.js";
import { isRecord } from "../utils/json.js";
import { readBooleanMap, readOptionalString } from "./requestParsing.js";
import { sanitizeGlobalRuntimeStatus } from "./runtimeRoutes.js";
export function formatCreateRunResult(result) {
    return {
        workspace: formatPublicWorkspaceRecord(result.workspace),
        run: formatPublicRunRecord(result.run),
        runtime: formatRunCreationRuntimeStatus(result.runtime),
        session: { state: "created" },
    };
}
export function formatPromptResult(result, submission) {
    return {
        accepted: result.accepted,
        run: formatPublicRunRecord(result.run),
        submission: {
            delivery: "accepted",
            textLength: submission.textLength,
            hasModel: submission.hasModel,
        },
    };
}
export function readSessionCreateInput(session, fallbackTitle) {
    const result = {};
    const fallback = readOptionalString(fallbackTitle);
    if (fallback)
        result.title = fallback;
    if (isRecord(session)) {
        const title = readOptionalString(session.title);
        const agent = readOptionalString(session.agent);
        if (title)
            result.title = title;
        if (agent)
            result.agent = agent;
    }
    return Object.keys(result).length > 0 ? result : undefined;
}
export function readRunSourceBinding(value) {
    if (!isRecord(value))
        return undefined;
    const workItemId = readBoundedIdentifier(value.workItemId, 80);
    const repositoryId = readBoundedIdentifier(value.repositoryId, 80);
    const preparationId = readBoundedIdentifier(value.preparationId, 80);
    const runIntentId = readBoundedIdentifier(value.runIntentId, 80);
    const branchPlanId = readBoundedIdentifier(value.branchPlanId, 80);
    const branchName = readBoundedBranchName(value.branchName, 120);
    const baseBranch = readBoundedBranchName(value.baseBranch, 80);
    if (!workItemId ||
        !repositoryId ||
        !branchPlanId ||
        !branchName ||
        !baseBranch) {
        return undefined;
    }
    return {
        workItemId,
        repositoryId,
        ...(preparationId ? { preparationId } : {}),
        ...(runIntentId ? { runIntentId } : {}),
        branchPlanId,
        branchName,
        baseBranch,
    };
}
export function readPromptOptions(body) {
    const result = {};
    const agent = readOptionalString(body.agent);
    const system = readOptionalString(body.system);
    const variant = readOptionalString(body.variant);
    const tools = readBooleanMap(body.tools);
    const model = readPromptModel(body.model);
    if (agent)
        result.agent = agent;
    if (typeof body.noReply === "boolean")
        result.noReply = body.noReply;
    if (system)
        result.system = system;
    if (variant)
        result.variant = variant;
    if (tools)
        result.tools = tools;
    if (model)
        result.model = model;
    return Object.keys(result).length > 0 ? result : undefined;
}
export function readRunCapPolicy(value) {
    if (!isRecord(value))
        return undefined;
    const policy = {};
    const costUsdPerRun = readBoundedPositiveNumber(value.costUsdPerRun, 1_000_000);
    const wallTimeSecondsPerRun = readBoundedPositiveNumber(value.wallTimeSecondsPerRun, 86_400);
    if (costUsdPerRun !== undefined)
        policy.costUsdPerRun = costUsdPerRun;
    if (wallTimeSecondsPerRun !== undefined) {
        policy.wallTimeSecondsPerRun = Math.trunc(wallTimeSecondsPerRun);
    }
    return Object.keys(policy).length > 0 ? policy : undefined;
}
function formatPublicWorkspaceRecord(workspace) {
    return {
        id: workspace.id,
        createdAt: workspace.createdAt,
        updatedAt: workspace.updatedAt,
        storage: {
            localRoot: workspace.rootPath.length > 0 ? "configured" : "missing",
        },
    };
}
function formatPublicRunRecord(run) {
    return {
        id: run.id,
        workspace: { id: run.workspaceId },
        status: run.status,
        ...(run.sourceWorkItemId && run.sourceRepositoryId
            ? {
                source: {
                    workItemId: run.sourceWorkItemId,
                    repositoryId: run.sourceRepositoryId,
                    ...(run.sourcePreparationId
                        ? { preparationId: run.sourcePreparationId }
                        : {}),
                    ...(run.sourceRunIntentId
                        ? { runIntentId: run.sourceRunIntentId }
                        : {}),
                },
            }
            : {}),
        ...(run.branchPlanId && run.branchName && run.baseBranch
            ? {
                branchPlan: {
                    id: run.branchPlanId,
                    name: run.branchName,
                    baseBranch: run.baseBranch,
                },
            }
            : {}),
        ...(run.title ? { title: run.title } : {}),
        ...(run.lastError
            ? { lastError: redactPublicDiagnosticText(run.lastError) }
            : {}),
        ...(run.attemptCount !== undefined
            ? { attemptCount: run.attemptCount }
            : {}),
        ...(run.previousRunId ? { previousRunId: run.previousRunId } : {}),
        createdAt: run.createdAt,
        updatedAt: run.updatedAt,
    };
}
function readBoundedIdentifier(value, maxLength) {
    const text = readOptionalString(value);
    if (!text || text.length > maxLength)
        return undefined;
    return /^[A-Za-z0-9][A-Za-z0-9:_-]*$/.test(text) ? text : undefined;
}
function readBoundedBranchName(value, maxLength) {
    const text = readOptionalString(value);
    if (!text || text.length > maxLength)
        return undefined;
    if (text.startsWith("/") || text.endsWith("/") || text.includes("//")) {
        return undefined;
    }
    if (text.includes("..") || text.includes("\\") || text.includes("~")) {
        return undefined;
    }
    return /^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(text) ? text : undefined;
}
function readBoundedPositiveNumber(value, max) {
    if (typeof value !== "number" || !Number.isFinite(value))
        return undefined;
    if (value <= 0 || value > max)
        return undefined;
    return value;
}
function formatRunCreationRuntimeStatus(runtime) {
    const sanitized = sanitizeGlobalRuntimeStatus(runtime, {
        includeProcess: true,
        includeDiagnostics: true,
    });
    if (!isRecord(sanitized))
        return {};
    const { provider: _provider, ...publicRuntime } = sanitized;
    return publicRuntime;
}
function readPromptModel(value) {
    if (!isRecord(value))
        return undefined;
    const providerID = readOptionalString(value.providerID);
    const modelID = readOptionalString(value.modelID);
    if (!providerID || !modelID)
        return undefined;
    return { providerID, modelID };
}
