"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildWorkerEventHookDraftContract = buildWorkerEventHookDraftContract;
exports.validateWorkerEventHookDraftSemanticRules = validateWorkerEventHookDraftSemanticRules;
const node_path_1 = __importDefault(require("node:path"));
const zod_1 = require("zod");
const structured_contract_support_1 = require("./structured-contract-support");
const validation_issues_1 = require("./validation-issues");
const workerEventHookDraftSchema = zod_1.z
    .object({
    body: zod_1.z.string().min(1).describe("Complete hook file contents to write."),
    summary: zod_1.z
        .string()
        .min(1)
        .describe("Concise human-readable summary of the generated hook."),
})
    .strict()
    .describe("Event hook file draft.");
function buildWorkerEventHookDraftContract(input) {
    return (0, structured_contract_support_1.buildWorkerStructuredContract)({
        schema: workerEventHookDraftSchema,
        example: buildWorkerEventHookDraftExample(input),
        rules: buildWorkerEventHookDraftRules(input),
    });
}
function validateWorkerEventHookDraftSemanticRules(draft, input) {
    const issues = [];
    if (draft.body.trim().length === 0) {
        (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
            path: ["body"],
            message: "body must not be empty.",
        });
    }
    if (draft.summary.trim().length === 0) {
        (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
            path: ["summary"],
            message: "summary must not be empty.",
        });
    }
    issues.push(...validateHookBodyForRunner(draft.body, input));
    return issues;
}
function validateHookBodyForRunner(body, input) {
    const extension = node_path_1.default.extname(input.hook.path);
    if (input.hook.runner === "worker" || extension === ".md") {
        return [];
    }
    switch (extension) {
        case ".js":
        case ".mjs":
        case ".cjs":
            return validateProgramHookBody(body, {
                stdinSignals: ["process.stdin"],
                stdoutSignals: ["console.log", "process.stdout.write"],
                jsonSignals: ["JSON.parse", "JSON.stringify"],
            });
        case ".py":
            return validateProgramHookBody(body, {
                stdinSignals: ["sys.stdin", "input("],
                stdoutSignals: ["print(", "sys.stdout.write"],
                jsonSignals: ["json."],
            });
        case ".sh":
            return validateProgramHookBody(body, {
                stdinSignals: ["read ", "cat", "stdin"],
                stdoutSignals: ["echo", "printf"],
                jsonSignals: ["json", "jq"],
            });
        default:
            return validateProgramHookBody(body, {
                stdinSignals: ["stdin"],
                stdoutSignals: ["stdout", "print", "echo", "console.log"],
                jsonSignals: ["json"],
            });
    }
}
function validateProgramHookBody(body, requiredSignals) {
    const issues = [];
    const normalizedBody = body.toLowerCase();
    addMissingSignalIssue(issues, body, requiredSignals.stdinSignals, {
        message: "program hook body must read event JSON from stdin.",
    });
    addMissingSignalIssue(issues, body, requiredSignals.stdoutSignals, {
        message: "program hook body must write result JSON to stdout.",
    });
    addMissingSignalIssue(issues, body, requiredSignals.jsonSignals, {
        message: "program hook body must parse or serialize JSON.",
    });
    if (!normalizedBody.includes("status")) {
        (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
            path: ["body"],
            message: "program hook body must include a status field.",
        });
    }
    if (!normalizedBody.includes("summary")) {
        (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
            path: ["body"],
            message: "program hook body must include a summary field.",
        });
    }
    if (!/(completed|skipped|failed)/iu.test(body)) {
        (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
            path: ["body"],
            message: "program hook body must return completed, skipped, or failed status.",
        });
    }
    return issues;
}
function addMissingSignalIssue(issues, body, signals, input) {
    if (signals.some((signal) => body.includes(signal))) {
        return;
    }
    (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
        path: ["body"],
        message: input.message,
    });
}
function buildWorkerEventHookDraftExample(input) {
    if (input.hook.runner === "worker") {
        const text = buildWorkerEventHookWorkerDraftExampleText(input.outputLanguage);
        return {
            body: text.body,
            summary: text.summary,
        };
    }
    const summary = buildWorkerEventHookProgramDraftSummary(input.outputLanguage, node_path_1.default.extname(input.hook.path));
    switch (node_path_1.default.extname(input.hook.path)) {
        case ".py":
            return {
                body: [
                    "import json",
                    "import sys",
                    "",
                    "event = json.load(sys.stdin)",
                    "print(f\"received {event['eventId']}\", file=sys.stderr)",
                    "print(json.dumps({",
                    '    "status": "completed",',
                    "    \"summary\": f\"Handled {event['issue']['displayId']}\",",
                    "}))",
                ].join("\n"),
                summary,
            };
        case ".sh":
            return {
                body: [
                    "#!/usr/bin/env bash",
                    "set -euo pipefail",
                    "",
                    'event_json="$(cat)"',
                    "event_id=\"$(printf '%s' \"$event_json\" | jq -r '.eventId')\"",
                    "summary=\"$(printf '%s' \"$event_json\" | jq -r '.issue.displayId')\"",
                    'printf "received %s\\n" "$event_id" >&2',
                    'printf \'{"status":"completed","summary":"Handled %s"}\\n\' "$summary"',
                ].join("\n"),
                summary,
            };
    }
    return {
        body: [
            'let input = "";',
            'process.stdin.setEncoding("utf8");',
            "for await (const chunk of process.stdin) input += chunk;",
            "const event = JSON.parse(input);",
            'console.error("received " + event.eventId);',
            "console.log(JSON.stringify({",
            '  status: "completed",',
            '  summary: "Handled " + event.issue.displayId',
            "}));",
        ].join("\n"),
        summary,
    };
}
function buildWorkerEventHookWorkerDraftExampleText(locale) {
    switch (locale) {
        case "ja":
            return {
                body: [
                    "# 人の確認が必要なときに通知する",
                    "",
                    "`matchedTriggers` に `aiNeedsHuman` が含まれる場合、簡潔なSlack DMを送信する。",
                    "repository、issue display ID、issue title、issue URL、matched triggers、result summaryを含める。",
                    "",
                    "通知が不要なeventの場合は `skipped` を返す。",
                ].join("\n"),
                summary: "人の確認通知用のMarkdown worker hookを作成しました。",
            };
        case "zh":
            return {
                body: [
                    "# 需要人工确认时通知",
                    "",
                    "当 `matchedTriggers` 包含 `aiNeedsHuman` 时，发送简短的Slack DM。",
                    "包含repository、issue display ID、issue title、issue URL、matched triggers和result summary。",
                    "",
                    "当event不需要通知时返回 `skipped`。",
                ].join("\n"),
                summary: "已创建用于人工关注通知的Markdown worker hook。",
            };
        case "en":
            return {
                body: [
                    "# Notify on Needs Human",
                    "",
                    "Send a concise Slack DM when `matchedTriggers` contains `aiNeedsHuman`.",
                    "Include the repository, issue display ID, issue title, issue URL, matched triggers, and result summary.",
                    "",
                    "Return `skipped` when the event does not require notification.",
                ].join("\n"),
                summary: "Created a Markdown worker hook for human attention notices.",
            };
    }
}
function buildWorkerEventHookProgramDraftSummary(locale, extension) {
    const languageName = extension === ".py" ? "Python" : extension === ".sh" ? "Bash" : "program";
    switch (locale) {
        case "ja":
            return `event JSONを読み取りJSONを返す${languageName} hookを作成しました。`;
        case "zh":
            return `已创建读取event JSON并返回JSON的${languageName} hook。`;
        case "en":
            return `Created a ${languageName} hook that reads event JSON and returns JSON.`;
    }
}
function buildWorkerEventHookDraftRules(input) {
    return [
        "Return exactly one JSON object in the decision block.",
        "body and summary are required.",
        "Return complete hook file contents in body. Do not return a diff, patch, or partial body.",
        "Design the hook body around the user's stated goal and the runtime event JSON fields; avoid hard-coded repository, issue, or pull request details unless the user explicitly requested them.",
        "Do not execute Slack, webhook, file writes, shell commands, network calls, or other side effects while drafting. Only write the hook file content in the JSON result.",
        "Do not include path, runner, scope, or trigger metadata in the JSON result; those are fixed by the command input.",
        `The hook path is ${input.hook.path}.`,
        `The runner is ${input.hook.runner}.`,
        `The registered triggers are ${input.hook.on.join(", ")}.`,
        ...(input.hook.runner === "worker"
            ? [
                "For a Markdown worker hook, body must be clear execution instructions for the dedicated hook worker.",
                "The Markdown hook should tell the worker when to return completed, skipped, or failed.",
            ]
            : [
                "For a program hook, body must read the event JSON from stdin.",
                "For a program hook, body must write exactly one JSON object to stdout with status completed, skipped, or failed and a summary string.",
                "Program hook logs must go to stderr, not stdout.",
            ]),
        ...(input.operation === "update"
            ? [
                "Use the current hook body as the baseline and preserve correct existing behavior unless the prompt asks to change it.",
            ]
            : []),
    ];
}
