/**
 * Modular section builders for the Drift Analysis prompt,
 * mirroring the recommendationSections.ts pattern.
 */
export function buildActionDecisionMatrix() {
    return `<decision_rules>
## Action Decision Tree

For each existing test, work through these checks in order — the first match wins:

1. **All endpoints the test covers were removed** → **DELETE**
2. **Some endpoints removed, some renamed** → **UPDATE**
3. **New response field added to a covered endpoint** → **UPDATE** — the test needs a new assertion even if existing assertions still pass
4. **Shape change breaks assertions (field-level: ≤2 fields changed, renamed, or type-swapped)** → **UPDATE**
   **Shape change restructures the root response (flat→nested, new wrapper object, root key renamed, ≥50% of test assertions broken)** → **REGENERATE**
5. **Auth added or auth method changed** → **UPDATE**
   **Auth removed** → **VERIFY**
6. **No breaking changes detected** → **IGNORE** or **VERIFY** for minor drift

Rules:
- DELETE when all covered endpoints no longer exist; REGENERATE when they still exist but changed drastically.
- REGENERATE means: the top-level response shape changed (flat→nested, new wrapper object added, root key renamed), OR ≥50% of the test's assertions reference fields that were removed or restructured. In all other cases, prefer UPDATE.
- Prefer UPDATE over REGENERATE when changes are field-level (≤2 fields added, removed, renamed, or type-swapped).
- Prefer IGNORE over VERIFY when all changed files are unrelated to the test's endpoint.
- ADD actions belong in the next step — complete this assessment with IGNORE / VERIFY / UPDATE / REGENERATE / DELETE only.

<examples>
<example>
Diff adds one field to a response object and renames a URL path segment:
\`\`\`
- @app.route("/users/<id>/orders")
+ @app.route("/users/<id>/purchases")
+ "total_items": len(order.items)
\`\`\`
→ **UPDATE**: path rename + one new field — both are field-level changes. Patch the URL and add an assertion for \`total_items\`.
</example>
<example>
Diff wraps the entire response in a new envelope object:
\`\`\`
- return Response({"id": ..., "status": ..., "items": [...]})
+ return Response({"data": {"id": ..., "status": ..., "items": [...]}, "meta": {"page": 1}})
\`\`\`
→ **REGENERATE**: root shape changed from a flat object to \`{data, meta}\`. Every existing assertion (e.g. \`response["id"]\`, \`response["status"]\`) is broken — rewrite the test from scratch.
</example>
</examples>
</decision_rules>`;
}
export function buildBreakingChangePatterns() {
    return `## Breaking Change Patterns to Detect

Scan the diff lines for these high-signal patterns:

### Endpoint-level breaking changes
- \`-  @app.route("/old-path")\` / \`+  @app.route("/new-path")\` — renamed endpoint
- \`-  router.get("/old")\` / \`+  router.get("/new")\` — renamed route
- \`-  @GetMapping("/old")\` / \`+  @GetMapping("/new")\` — Spring rename
- Lines removing a route decorator entirely (endpoint removed)

### Request/response shape changes
- Field type changes: \`- field: int\` → \`+ field: string\`
- Required field added: \`+ required: [..., "newField"]\`
- Response field removed: \`- "responseField":\`
- Enum value changes: \`- status: "active"\` → \`+ status: "enabled"\`

### Auth changes
- \`+ @require_auth\`, \`+ @login_required\`, \`+ middleware(authMiddleware)\`
- \`- @require_auth\` (auth removed)
- Token type changed: Bearer → Cookie

### Status code changes
- \`- return 200\` → \`+ return 201\`
- \`- status_code=200\` → \`+ status_code=204\`
- \`- res.status(201)\` → \`+ res.status(200)\`

### Additive response field changes (non-breaking but coverage gap)
These do NOT break existing assertions but leave the new field untested. Always flag as UPDATE for covered endpoints.
- \`+ "newField": queryset.filter(...).count()\` added inside a \`Response({...})\` or \`res.json({...})\`
- \`+ newField = serializers.XXXField()\` added to a serializer used by a tested endpoint
- \`+ "newField":\` added to a response body dict returned by the endpoint
- New key added inside an existing dict/object returned by the endpoint`;
}
export function buildTestAssessmentGuidelines() {
    return `## Per-Test Assessment (4 Checks)

For each existing test file, run these checks:

### Check A: Endpoint existence
Does the endpoint the test targets still exist in the codebase?
- If ALL endpoints the test covers were removed → action: DELETE (the entire test file is obsolete)
- If SOME methods were removed but others remain → action: UPDATE (remove the test functions for deleted methods, keep the rest)
- If the endpoint was renamed → action: UPDATE (path substitution)

### Check B: Request/response shape (breaking changes)
Has the request body or response structure changed in a way that breaks the test?
- Compare test's expected fields against current schema/model definitions
- Type changes (string→int, int→string) on individual fields → action: UPDATE
- Type change restructures the root object or makes the entire request body invalid → action: REGENERATE
- New required fields the test doesn't send → action: UPDATE
- Response fields the test asserts on have been removed → action: UPDATE
- ≥50% of the test's assertions reference fields that were removed or restructured → action: REGENERATE

**UPDATE vs REGENERATE:** choose UPDATE when changes are field-level (≤2 fields added, removed, renamed, or type-swapped). Choose REGENERATE only when the root response shape changed (flat→nested, new wrapper object, root key renamed) or ≥50% of assertions are broken.

### Check B2: Additive response field changes (coverage gaps)
**Even if existing assertions still pass**, does the diff add a new field to the response of an endpoint this test already covers?
- Look at the diff for lines like \`+ "newField":\` or \`+ newField =\` inside a view/serializer this test hits
- If YES → action: UPDATE
- This applies even when the test only checks status codes — the test should be extended to cover the new field
- A new response field on a covered endpoint always triggers UPDATE — even when existing assertions still pass.

### Check C: Auth changes
Has the authentication mechanism for this endpoint changed?
- Auth added where none existed → action: UPDATE
- Auth method changed (bearer→cookie) → action: UPDATE
- Auth removed → action: VERIFY

### Check D: Assign action
Based on the above, choose the action (IGNORE / VERIFY / UPDATE / REGENERATE / DELETE) and provide a 1-2 sentence rationale.
- If Check B2 flagged an additive field → action must be UPDATE, even if Checks B/C found no breaking changes.`;
}
export function buildAddRecommendationGuidelines() {
    return `## ADD — New Tests for New Endpoints

**ADD applies only when:**
- The diff introduces a brand-new route that has **no existing test coverage at all**, OR
- The diff introduces a new auth path, error branch, or fundamentally separate scenario that no existing test covers.

**Use UPDATE instead of ADD when:**
- The resource already has existing tests and the diff only adds a new HTTP method — add the new method's test cases to the existing file.
- The endpoint existed before this diff but lacks tests — log it in \`additionalRecommendations\` and skip it; pre-existing coverage gaps are out of scope for ADD.

**Test type priority by HTTP method:**
| Method | Recommended test types |
|--------|----------------------|
| POST / PUT / PATCH | integration, contract |
| GET | contract, smoke |
| DELETE | integration, smoke |

Use a unique descriptive filename for every new test file. For a resource with existing tests, update the existing file — always prefer UPDATE over creating a new file.`;
}
export function buildUpdateExecutionRules() {
    return `<execution_rules>
## Update Execution Rules

When applying UPDATE actions to existing test files, follow these rules in addition to the drift-detected changes:

### Test file ordering
Place mutation test functions (PATCH, PUT, POST) **before** any DELETE test function targeting the same resource. DELETE removes the resource — any mutation call after it will 404. When inserting a new mutation test, place it above the DELETE function and above the DELETE call in the \`if __name__ == "__main__"\` block (or equivalent runner entrypoint).

### Happy path first
When adding a new HTTP method (PUT, PATCH, POST) to an existing test file, always include a 2xx success assertion first. Error-path tests (404, 422) may follow, but the happy path case is required.

### All test files for a resource
When a diff adds a new HTTP method to a resource, UPDATE covers **all** existing test files for that resource — contract, integration, and UI. Apply UPDATE to every file the analyze tool reported for that resource path; do not stop after updating the first one.

### PATCH/PUT with child collections
Child collection arrays (e.g. \`items\`, \`products\`, \`line_items\`) drive computed totals — a test that omits them cannot catch the most common mutation bugs. When the request/response includes a child collection:
1. Include the child array with at least one item containing the FK field (e.g. \`product_id\`) and a \`quantity\` field.
2. Assert each item's FK field and \`quantity\` match the sent values.
3. Assert the top-level computed total (e.g. \`total_amount\`) equals the expected math from the items.

### REGENERATE
Call the appropriate generation tool to replace the existing test from scratch. Use the same filename so it overwrites the old file.

### DELETE
Remove the test file when ALL endpoints it covers were removed from the codebase. If only SOME methods were removed, use UPDATE instead — remove the test functions for deleted methods and keep the rest.

### Test data isolation
Never use hardcoded resource IDs (e.g. \`order_id=1\`) in any test step, including GET or DELETE steps. Always create required resources via prior POST steps and chain IDs dynamically. Use timestamp-based unique names for created resources (e.g. \`"Product-\${int(time.time())}"\`) to prevent collisions across test runs.

### Enhance assertions after UPDATE
Call \`skyramp_enhance_assertions\` with \`testFile\` set to the absolute path of the test file you just updated, \`enhanceType: "maintenance"\`, and the matching \`testType\` based on the file you are editing:
- **Integration test file** (multi-step chained requests): call with \`testType: "integration"\`
- **Contract-provider test file** (single endpoint with \`beforeAll\`/\`afterAll\` setup, provider mode): call with \`testType: "contract"\`. Skip for consumer-mode contract tests.
- **UI test file** (imports \`@playwright/test\`, uses \`page.\` calls): call with \`testType: "ui"\`

Then apply every instruction returned by the tool to the test file.
</execution_rules>`;
}
export function buildDriftOutputChecklist(existingTestCount, newEndpointCount, inlineMode = false, stateFile) {
    const finalStep = inlineMode
        ? `### Final step
Apply all maintenance actions (UPDATE / REGENERATE / DELETE) directly by editing the test files. Apply IGNORE, VERIFY, UPDATE, REGENERATE, or DELETE only — ADD is handled in the next task.`
        : `### Final step
After completing all assessments above, call \`skyramp_actions\` with \`stateFile: "${stateFile ?? "<stateFile>"}"\` and a \`recommendations\` entry for every test assessed. For each entry include: \`testFile\` (absolute path as reported by the analysis tools), \`action\`, \`rationale\`, \`updateInstructions\` (free-form summary of what this test must change — new fields to assert, constraint details, auth changes, new request params, or any other drift specifics; \`skyramp_actions\` passes this directly to the downstream LLM editing the file), and \`renamedEndpoints\` (for path-rename updates).

Call \`skyramp_actions\` as the sole final action — skip all other file writes.`;
    const existingTestHeader = inlineMode
        ? "### Existing tests (reported by skyramp_analyze_changes)"
        : `### Existing tests (${existingTestCount} total)`;
    const existingTestSection = `${existingTestHeader}
For each existing test:
- **IGNORE/VERIFY tests**: one line each: \`{testFile} — IGNORE\` or \`{testFile} — VERIFY\`. Rationale omitted for brevity.
- **UPDATE/REGENERATE/DELETE tests**: output the full block:
\`\`\`
Test: {testFile}
Action: {UPDATE | REGENERATE | DELETE}
Rationale: {1-2 sentence explanation}
\`\`\`
Focus your analysis on tests that need action — keep reasoning for unchanged tests to a single line.`;
    const newEndpointSection = inlineMode
        ? ""
        : newEndpointCount > 0
            ? `### New endpoints (${newEndpointCount} detected)
For EACH new endpoint, output:
\`\`\`
Endpoint: {METHOD} {path}
Action: ADD
Test types: {contract | integration | smoke | ...}
Rationale: {1 sentence}
\`\`\``
            : `### New endpoints
No new endpoints detected in this diff.`;
    const sections = [existingTestSection, newEndpointSection, finalStep].filter(s => s.length > 0);
    return `<output_format>
## Output Checklist

Complete ALL of the following:

${sections.join("\n\n")}
Be brief. Decide the action for each test and apply edits immediately. Limit reasoning for IGNORE'd tests to a single line.
</output_format>`;
}
