/**
 * pipeline/degradations.ts
 *
 * Programmatic code degradation strategies for sensitivity testing.
 *
 * Each strategy takes a "good" reference solution (string) and returns a
 * "bad" version that should score lower on a specific dimension:
 *
 * - Task Completion: remove key functional sections
 * - Code Correctness: introduce anti-patterns and deprecated APIs
 * - Doc Coverage: strip documentation references, add hallucinated details
 *
 * These are deterministic, pure functions — no randomness, no side effects.
 *
 * @see docs/archive/exec-plans/grader-reliability.md — Phase 4
 */
// ---------------------------------------------------------------------------
// Task Completion degradations
// ---------------------------------------------------------------------------
/**
 * Remove the bottom half of the code (functions, exports, etc).
 * A response missing half its functionality should score lower on Task Completion.
 */
export const removeBottomHalf = {
    apply(source) {
        const lines = source.split("\n");
        const midpoint = Math.floor(lines.length / 2);
        const kept = lines.slice(0, midpoint);
        kept.push("");
        kept.push("// ... (remaining implementation not provided)");
        return kept.join("\n");
    },
    description: "Remove bottom half of code — missing key functionality",
    targetDimension: "taskCompletion",
};
/**
 * Remove all export statements and exported functions.
 * Missing exports = incomplete API surface → lower Task Completion.
 */
export const removeExports = {
    apply(source) {
        const lines = source.split("\n");
        return lines
            .filter((line) => {
            const trimmed = line.trim();
            // Remove export declarations
            if (trimmed.startsWith("export "))
                return false;
            // Remove lines that are just "export {"
            if (/^export\s*\{/.test(trimmed))
                return false;
            return true;
        })
            .join("\n");
    },
    description: "Remove export statements — incomplete public API",
    targetDimension: "taskCompletion",
};
/**
 * Replace function bodies with TODO comments.
 * Skeleton code that doesn't actually implement anything.
 */
export const stubFunctions = {
    apply(source) {
        // Match function/method declarations and replace their bodies
        // This handles: async function foo() { ... }, function foo() { ... },
        // const foo = async () => { ... }, etc.
        return source.replace(/(\{)\s*\n([\s\S]*?)(\n\s*\})/g, (match, open, _body, close) => {
            // Only replace if the body has more than 2 lines (avoid replacing object literals)
            const bodyLines = _body.split("\n").filter((l) => l.trim().length > 0);
            if (bodyLines.length < 3)
                return match;
            return `${open}\n  // TODO: implement\n  throw new Error("Not implemented")\n${close}`;
        });
    },
    description: "Replace function bodies with TODO stubs — no implementation",
    targetDimension: "taskCompletion",
};
// ---------------------------------------------------------------------------
// Code Correctness degradations
// ---------------------------------------------------------------------------
/**
 * Replace modern API calls with deprecated/incorrect patterns.
 * Targets Sanity-specific patterns that the grader should catch.
 */
export const introduceDeprecatedAPIs = {
    apply(source) {
        let result = source;
        // Replace createClient with deprecated @sanity/client import
        result = result.replace(/import\s*\{\s*createClient\s*\}\s*from\s*["']@sanity\/client["']/g, 'import sanityClient from "@sanity/client" // deprecated default import');
        result = result.replace(/import\s*\{\s*createClient\s*\}\s*from\s*["']next-sanity["']/g, 'import sanityClient from "next-sanity" // deprecated default import');
        // Replace defineType/defineField with plain objects
        result = result.replace(/import\s*\{[^}]*defineType[^}]*\}\s*from\s*["']sanity["']/g, "// Using plain objects instead of defineType/defineField");
        result = result.replace(/defineType\(\{/g, "({");
        result = result.replace(/defineField\(\{/g, "({");
        // Replace apiVersion with very old version
        result = result.replace(/apiVersion:\s*["'][^"']+["']/g, 'apiVersion: "2021-03-25" // outdated API version');
        // Replace useCdn: true with useCdn: false (incorrect for read-only)
        result = result.replace(/useCdn:\s*true/g, "useCdn: false // unnecessary");
        return result;
    },
    description: "Replace modern APIs with deprecated patterns",
    targetDimension: "codeCorrectness",
};
/**
 * Introduce common GROQ syntax errors.
 * Invalid queries that look plausible but wouldn't work.
 */
export const introduceGroqErrors = {
    apply(source) {
        let result = source;
        // Replace -> dereference with . (incorrect)
        result = result.replace(/->/g, ".");
        // Replace valid array slice [0...10] with incorrect [0:10]
        result = result.replace(/\[(\d+)\.\.\.(\d+)\]/g, "[$1:$2]");
        // Replace references() with invalid refs()
        result = result.replace(/references\(/g, "refs(");
        // Replace | order() with incorrect .sort()
        result = result.replace(/\|\s*order\(/g, ".sort(");
        return result;
    },
    description: "Introduce GROQ syntax errors — plausible but broken queries",
    targetDimension: "codeCorrectness",
};
/**
 * Remove all TypeScript types and use any everywhere.
 * Technically works but is an anti-pattern.
 */
export const removeTypes = {
    apply(source) {
        let result = source;
        // Remove interface/type declarations
        result = result.replace(/^(?:export\s+)?(?:interface|type)\s+\w+[\s\S]*?^\}/gm, "");
        // Replace typed parameters with any
        result = result.replace(/:\s*[A-Z]\w+(?:\[\])?(?:\s*\|[^,)]+)?/g, ": any");
        // Replace Promise<Type> with Promise<any>
        result = result.replace(/Promise<[^>]+>/g, "Promise<any>");
        // Remove generic type parameters
        result = result.replace(/<[A-Z]\w+(?:\[\])?>/g, "");
        return result;
    },
    description: "Strip TypeScript types and use 'any' — works but anti-pattern",
    targetDimension: "codeCorrectness",
};
// ---------------------------------------------------------------------------
// Doc Coverage degradations
// ---------------------------------------------------------------------------
/**
 * Remove all comments and documentation.
 * The response shows no evidence of using documentation.
 */
export const stripComments = {
    apply(source) {
        const lines = source.split("\n");
        return (lines
            .filter((line) => {
            const trimmed = line.trim();
            // Remove single-line comments
            if (trimmed.startsWith("//"))
                return false;
            // Remove JSDoc comment blocks
            if (trimmed.startsWith("*") ||
                trimmed.startsWith("/**") ||
                trimmed.startsWith("*/"))
                return false;
            return true;
        })
            .join("\n")
            // Remove remaining inline comments
            .replace(/\s*\/\/[^"']*$/gm, "")
            // Remove multi-line comments
            .replace(/\/\*[\s\S]*?\*\//g, "")
            // Clean up excessive blank lines
            .replace(/\n{3,}/g, "\n\n"));
    },
    description: "Remove all comments — no evidence of documentation usage",
    targetDimension: "docCoverage",
};
/**
 * Add hallucinated API calls and made-up configuration options.
 * Response looks confident but uses APIs that don't exist.
 */
export const addHallucinations = {
    apply(source) {
        const hallucinations = [
            "\n// Enable real-time sync (recommended for production)",
            'const sync = client.enableRealTimeSync({ mode: "aggressive" })',
            "",
            "// Configure auto-indexing for faster queries",
            'client.configureIndex({ fields: ["title", "slug"], type: "fulltext" })',
            "",
            "// Use built-in caching middleware",
            'import { withSanityCache } from "@sanity/cache-middleware"',
            "const cachedClient = withSanityCache(client, { ttl: 3600 })",
            "",
        ];
        return hallucinations.join("\n") + "\n" + source;
    },
    description: "Add hallucinated APIs — confident but wrong information",
    targetDimension: "docCoverage",
};
/**
 * Replace correct import paths with plausible but wrong ones.
 * Shows the response was guessing at the API surface.
 */
export const wrongImports = {
    apply(source) {
        let result = source;
        // Replace real packages with plausible wrong ones
        result = result.replace(/from\s*["']@sanity\/client["']/g, 'from "sanity-client"');
        result = result.replace(/from\s*["']next-sanity["']/g, 'from "@next/sanity"');
        result = result.replace(/from\s*["']sanity["']/g, 'from "@sanity/core"');
        result = result.replace(/from\s*["']sanity\/presentation["']/g, 'from "@sanity/presentation-tool"');
        result = result.replace(/from\s*["']sanity\/structure["']/g, 'from "@sanity/desk-tool"');
        result = result.replace(/from\s*["']sanity\/functions["']/g, 'from "@sanity/serverless"');
        return result;
    },
    description: "Replace imports with wrong packages — guessing at API surface",
    targetDimension: "docCoverage",
};
// ---------------------------------------------------------------------------
// Strategy registry
// ---------------------------------------------------------------------------
/** All available degradation strategies, grouped by target dimension */
export const DEGRADATION_STRATEGIES = [
    // Task Completion
    removeBottomHalf,
    removeExports,
    stubFunctions,
    // Code Correctness
    introduceDeprecatedAPIs,
    introduceGroqErrors,
    removeTypes,
    // Doc Coverage
    stripComments,
    addHallucinations,
    wrongImports,
];
/** Get degradation strategies targeting a specific dimension */
export function getStrategiesForDimension(dimension) {
    return DEGRADATION_STRATEGIES.filter((s) => s.targetDimension === dimension);
}
