"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.openPublishPullRequest = openPublishPullRequest;
const control_plane_config_1 = require("../config/control-plane-config");
const native_git_cli_1 = require("../git/native-git-cli");
const catalog_1 = require("../i18n/catalog");
const issue_template_discovery_1 = require("../issues/issue-template-discovery");
const constants_1 = require("../platform/constants");
const PUBLISH_PR_CONTEXT_MAX_CHARS = 12_000;
const PUBLISH_PR_CONTEXT_COMMAND_TIMEOUT_MS = 15_000;
async function openPublishPullRequest(input) {
    const title = buildPullRequestTitle(input.message);
    const pullRequest = await ensurePublishPullRequest({
        repositoryHost: input.repositoryHost,
        branchName: input.branchName,
        baseBranch: input.baseBranch,
        title,
        locale: input.locale,
        createBody: createPublishPullRequestBodyResolver({
            cwd: input.cwd,
            config: input.config,
            branchName: input.branchName,
            baseBranch: input.baseBranch,
            remoteName: input.remoteName,
            title,
            run: input.run,
            locale: input.locale,
            createWorkerRuntime: input.createWorkerRuntime,
            now: input.now,
        }),
    });
    console.log((0, catalog_1.translate)(input.locale, pullRequest.source === "existing"
        ? "publish.command.prExisting"
        : "publish.command.prCreated", { url: pullRequest.pullRequest.url }));
    return pullRequest;
}
function buildPullRequestTitle(message) {
    return message.split(/\r?\n/, 1)[0]?.trim() || "chore: publish local changes";
}
async function ensurePublishPullRequest(input) {
    const existing = await input.repositoryHost.findPullRequestByBranch(input.branchName);
    if (existing?.state === constants_1.PLATFORM_PULL_REQUEST_STATES.open) {
        if (existing.baseBranch !== input.baseBranch) {
            throw new Error((0, catalog_1.translate)(input.locale, "publish.command.existingPrBaseMismatch", {
                branchName: input.branchName,
                existingBaseBranch: existing.baseBranch,
                baseBranch: input.baseBranch,
            }));
        }
        return { source: "existing", pullRequest: existing };
    }
    const body = await input.createBody();
    const pullRequest = await input.repositoryHost.createPullRequest({
        title: input.title,
        body,
        headBranch: input.branchName,
        baseBranch: input.baseBranch,
        draft: false,
    });
    return { source: "created", pullRequest };
}
function buildPublishPullRequestFallbackBody(input) {
    return (0, catalog_1.translate)(input.locale, "publish.command.fallbackPrBody", {
        branchName: input.branchName,
        baseBranch: input.baseBranch,
    });
}
function createPublishPullRequestBodyResolver(input) {
    return () => resolvePublishPullRequestBody({
        ...input,
        fallbackBody: buildPublishPullRequestFallbackBody({
            locale: input.locale,
            branchName: input.branchName,
            baseBranch: input.baseBranch,
        }),
    });
}
async function resolvePublishPullRequestBody(input) {
    if ((0, control_plane_config_1.resolveWorkersForPurpose)(input.config, "thinking").length === 0) {
        return input.fallbackBody;
    }
    try {
        const context = await collectPublishPullRequestContext(input);
        if (context === null) {
            return input.fallbackBody;
        }
        const templates = await (0, issue_template_discovery_1.discoverPullRequestTemplates)({
            repoRoot: input.cwd,
            repositoryHostKind: input.config.repositoryHost.kind,
        });
        const workerRuntime = await input.createWorkerRuntime(input.config);
        const draftResult = await workerRuntime.runIssueDraft({
            prompt: buildPublishPullRequestDraftPrompt({
                ...input,
                context,
            }),
            outputLanguage: input.config.i18n.defaultLanguage,
            acceptedAt: input.now().toISOString(),
            displayTimeZone: input.config.i18n.displayTimeZone,
            templateKind: "pull_request",
            availableIssueTemplates: (0, issue_template_discovery_1.toWorkerDraftTemplateCandidates)(templates),
            workspacePath: input.cwd,
            repositoryRoot: input.cwd,
        });
        if (draftResult.kind === "deferred") {
            return input.fallbackBody;
        }
        const body = draftResult.launchResult.draft.body.trim();
        return body.length > 0 ? body : input.fallbackBody;
    }
    catch {
        return input.fallbackBody;
    }
}
async function collectPublishPullRequestContext(input) {
    const baseRef = `refs/remotes/${input.remoteName}/${input.baseBranch}`;
    const commitLog = await readPublishGitContext(input, [
        "log",
        "--oneline",
        `${baseRef}..HEAD`,
    ]);
    const diffStat = await readPublishGitContext(input, [
        "diff",
        "--stat",
        `${baseRef}...HEAD`,
    ]);
    const nameStatus = await readPublishGitContext(input, [
        "diff",
        "--name-status",
        `${baseRef}...HEAD`,
    ]);
    const diff = await readPublishGitContext(input, [
        "diff",
        "--no-ext-diff",
        `${baseRef}...HEAD`,
    ]);
    if (commitLog === null || diffStat === null || nameStatus === null) {
        return null;
    }
    return {
        commitLog,
        diffStat,
        nameStatus,
        diff: diff ?? "",
    };
}
async function readPublishGitContext(input, args) {
    const result = await (0, native_git_cli_1.runNativeGitWithLegacyRunner)(input.run, {
        args,
        cwd: input.cwd,
        locale: input.locale,
        allowNonZeroExit: true,
        timeoutMs: PUBLISH_PR_CONTEXT_COMMAND_TIMEOUT_MS,
    });
    if (result.exitCode !== 0) {
        return null;
    }
    return truncatePublishPullRequestContext(result.stdout.trim());
}
function truncatePublishPullRequestContext(value) {
    if (value.length <= PUBLISH_PR_CONTEXT_MAX_CHARS) {
        return value;
    }
    return `${value.slice(0, PUBLISH_PR_CONTEXT_MAX_CHARS)}\n\n[truncated]`;
}
function buildPublishPullRequestDraftPrompt(input) {
    return [
        "Draft a pull request body for `alpaca publish`.",
        "",
        "Rules:",
        "- The pull request title is already set; do not write or change it.",
        "- Return the pull request body in the `body` field.",
        "- Return any short non-empty value in the `title` field; it will be ignored.",
        "- If a pull request template is selected, preserve its questions, headings, and order.",
        "- Mention verification only when it is directly supported by the provided changes.",
        "- Do not invent issue links, reviewers, deployment status, or test results.",
        "",
        "Publish metadata:",
        `- PR title: ${input.title}`,
        `- Head branch: ${input.branchName}`,
        `- Base branch: ${input.baseBranch}`,
        `- Fallback body: ${input.fallbackBody}`,
        "",
        "Commit log:",
        input.context.commitLog || "(none)",
        "",
        "Changed files:",
        input.context.nameStatus || "(none)",
        "",
        "Diff stat:",
        input.context.diffStat || "(none)",
        "",
        "Diff:",
        input.context.diff || "(not available)",
    ].join("\n");
}
