"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderInvalidInputTest = void 0;
const ts_morph_1 = require("ts-morph");
function renderInvalidInputTest(args) {
    const assertion = renderViolationAssertion({
        violationEffect: args.violationEffect,
        pageObjectName: args.pageObjectName,
        inputFieldName: args.inputFieldName,
        originalCallback: args.originalCallback,
        targetFillCall: args.targetFillCall,
    });
    const invalidConstName = `${args.inputFieldName}${args.kind === 'minlength' ? 'TooShort' : 'TooLong'}`;
    const invalidLiteral = toSingleQuotedStringLiteral(args.invalidValue);
    return (`test('${escapeSingleQuotes(args.testTitle)}', async (${args.testParams}) => {\n` +
        `  const ${invalidConstName} = ${invalidLiteral};\n` +
        `\n` +
        `${indentLines(args.prefixStatements.replaceAll(invalidLiteral, invalidConstName), 2)}\n` +
        `\n` +
        `${indentLines(assertion, 2)}\n` +
        `});`);
}
exports.renderInvalidInputTest = renderInvalidInputTest;
function renderViolationAssertion(args) {
    switch (args.violationEffect) {
        case 'ARIA_INVALID_STATE':
            return [
                `await ${args.pageObjectName}.${args.inputFieldName}.blur();`,
                `await expect(${args.pageObjectName}.${args.inputFieldName}).toHaveAttribute('aria-invalid', 'true');`,
            ].join('\n');
        case 'BUTTON_DISABLED': {
            const buttonProp = inferNextClickedButtonProperty({
                originalCallback: args.originalCallback,
                targetFillCall: args.targetFillCall,
                pageObjectName: args.pageObjectName,
            });
            if (!buttonProp) {
                return `// TODO(gremlin): schema says BUTTON_DISABLED, but no click*Button() call was found after the fill call to infer which button should be disabled.`;
            }
            return `await expect(${args.pageObjectName}.${buttonProp}).toBeDisabled();`;
        }
        case 'FAILURE':
            // Best-effort: common pattern in page objects.
            return `// TODO(gremlin): schema says FAILURE; add an assertion for the expected failure mode (e.g. error banner visible).`;
        default:
            return `// TODO(gremlin): unknown violationEffect: ${String(args.violationEffect)}`;
    }
}
function inferNextClickedButtonProperty(args) {
    const body = args.originalCallback.getBody().asKind(ts_morph_1.SyntaxKind.Block);
    if (!body)
        return null;
    const statements = body.getStatements();
    const targetStatement = statements.find((stmt) => stmt
        .getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression)
        .some((c) => c === args.targetFillCall));
    if (!targetStatement)
        return null;
    const idx = statements.indexOf(targetStatement);
    const after = statements.slice(idx + 1);
    for (const stmt of after) {
        const calls = stmt.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression);
        for (const call of calls) {
            const expr = call.getExpression();
            if (!ts_morph_1.Node.isPropertyAccessExpression(expr))
                continue;
            if (expr.getExpression().getText() !== args.pageObjectName)
                continue;
            const method = expr.getName();
            if (!method.startsWith('click') || !method.endsWith('Button'))
                continue;
            const suffix = method.slice('click'.length); // ContinueButton
            if (!suffix)
                continue;
            return suffix[0].toLowerCase() + suffix.slice(1);
        }
    }
    return null;
}
function indentLines(text, spaces) {
    const prefix = ' '.repeat(spaces);
    return text
        .split('\n')
        .map((line) => (line.trim().length === 0 ? line : prefix + line))
        .join('\n');
}
function escapeSingleQuotes(value) {
    return value.replaceAll("'", "\\'");
}
function toSingleQuotedStringLiteral(value) {
    return `'${value.replaceAll('\\', '\\\\').replaceAll("'", "\\'")}'`;
}
