import { buildActionDecisionTree, buildCheckAdditiveFields, buildCheckEndpointExistence, buildCheckResponseShape, buildCheckAuthAndAuthorization, buildCheckBehavioralContract, buildCheckAssignAction, buildDriftOutputChecklist, buildUpdateExecutionRules, } from "./driftAnalysisSections.js";
import { readDiffFile } from "../../utils/utils.js";
import { PromptPlan } from "../test-recommendation/promptPlan.js";
// ── Private body helpers ──────────────────────────────────────────────────────
// Each receives DriftAnalysisPromptParams and returns the step body string.
// The "### Step N: Title" header is added by PromptPlan.render().
function _assessBody(_p) {
    return buildActionDecisionTree();
}
function _checkAdditiveFieldsBody(_p) {
    return buildCheckAdditiveFields();
}
function _checkEndpointExistenceBody(_p) {
    return buildCheckEndpointExistence();
}
function _checkResponseShapeBody(_p) {
    return buildCheckResponseShape();
}
function _checkAuthAndAuthorizationBody(_p) {
    return buildCheckAuthAndAuthorization();
}
function _checkBehavioralContractBody(_p) {
    return buildCheckBehavioralContract();
}
function _checkAssignActionBody(_p) {
    return buildCheckAssignAction();
}
function _applyBody(_p) {
    return buildUpdateExecutionRules();
}
function _callToolBody(p) {
    return buildDriftOutputChecklist(p.existingTests.length, p.newEndpointCount ?? 0, p.stateFile);
}
// ── PromptPlan declaration ────────────────────────────────────────────────────
// All steps are unconditional — both MCP and testbot callers render the same
// five steps. The only per-caller variation is skipContextHeader (context
// section prepended by buildDriftAnalysisPrompt, not inside the plan).
const _plan = new PromptPlan()
    .addPhase("maintenance", "Test Maintenance Assessment", {
    headerLevel: "##",
    stepFormat: "hash",
})
    .step("ASSESS", "Action Decision Tree — assess each existing test against the diff", _assessBody)
    .subStep("ENDPOINT_EXISTENCE", "Endpoint existence", _checkEndpointExistenceBody)
    .subStep("RESPONSE_SHAPE", "Request/response shape (breaking changes)", _checkResponseShapeBody)
    .subStep("ADDITIVE_FIELDS", "Additive response fields (coverage gaps)", _checkAdditiveFieldsBody)
    .subStep("AUTH_AUTHZ", "Auth and authorization changes", _checkAuthAndAuthorizationBody)
    .subStep("BEHAVIORAL_CONTRACT", "Behavioral and semantic contract changes", _checkBehavioralContractBody)
    .subStep("ASSIGN_ACTION", "Assign action", _checkAssignActionBody)
    .step("APPLY", "Apply update execution rules", _applyBody)
    .step("CALL_TOOL", "Submit recommendations", _callToolBody)
    .done();
// ── Exported step label constants ─────────────────────────────────────────────
// Static — safe to export at module load; renumber automatically on insertion.
/** "1" — Assess each test against the diff */
export const DRIFT_STEP_ASSESS = _plan.labels.ASSESS; // "1"
/** "1.1" — Endpoint existence check */
export const DRIFT_STEP_ENDPOINT_EXISTENCE = _plan.labels.ENDPOINT_EXISTENCE; // "1.1"
/** "1.2" — Request/response shape check */
export const DRIFT_STEP_RESPONSE_SHAPE = _plan.labels.RESPONSE_SHAPE; // "1.2"
/** "1.3" — Additive response fields check */
export const DRIFT_STEP_ADDITIVE_FIELDS = _plan.labels.ADDITIVE_FIELDS; // "1.3"
/** "1.4" — Auth and authorization changes check */
export const DRIFT_STEP_AUTH_AUTHZ = _plan.labels.AUTH_AUTHZ; // "1.4"
/** "1.5" — Behavioral and semantic contract changes check */
export const DRIFT_STEP_BEHAVIORAL_CONTRACT = _plan.labels.BEHAVIORAL_CONTRACT; // "1.5"
/** "1.6" — Assign action */
export const DRIFT_STEP_ASSIGN_ACTION = _plan.labels.ASSIGN_ACTION; // "1.6"
/** "2" — Apply update execution rules */
export const DRIFT_STEP_APPLY = _plan.labels.APPLY; // "2"
/** "3" — Submit recommendations (calls skyramp_actions) */
export const DRIFT_STEP_CALL_TOOL = _plan.labels.CALL_TOOL; // "3"
// ── Public builder ────────────────────────────────────────────────────────────
export function buildDriftAnalysisPrompt(params) {
    // Pre-compute newEndpointCount from rawDiff only when caller did not supply it.
    // Use strict undefined check — an explicit 0 means "no new endpoints" and must
    // not trigger a diff read.
    let newEndpointCount = params.newEndpointCount ?? 0;
    if (params.newEndpointCount === undefined) {
        const rawDiff = readDiffFile(params.diffFilePath);
        if (rawDiff) {
            const m = rawDiff.match(/\*\*New Endpoints\*\*\s+\((\d+)\)/);
            if (m)
                newEndpointCount = parseInt(m[1], 10);
        }
    }
    const resolvedParams = { ...params, newEndpointCount };
    // Always emit the lean wrapped form — context is already in the conversation
    // from skyramp_analyze_changes, which always runs before this tool.
    return `<drift_analysis_rules>\n${_plan.render(resolvedParams)}\n</drift_analysis_rules>`;
}
