"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SecurityPredictor = void 0;
const typescript_1 = __importDefault(require("typescript"));
class SecurityPredictor {
    predict(code) {
        const predictions = [];
        const astPredictions = this.analyzeAst(code);
        predictions.push(...astPredictions);
        const lines = code.split('\n');
        for (let i = 0; i < lines.length; i++) {
            const line = lines[i];
            const lineNum = i + 1;
            const alreadyReported = astPredictions.some((p) => p.line === lineNum);
            if (!alreadyReported) {
                const sqlPrediction = this.checkSQLInjection(line, lineNum);
                if (sqlPrediction)
                    predictions.push(sqlPrediction);
                const pathPrediction = this.checkPathTraversal(line, lineNum);
                if (pathPrediction)
                    predictions.push(pathPrediction);
                const secretPrediction = this.checkHardcodedSecret(line, lineNum);
                if (secretPrediction)
                    predictions.push(secretPrediction);
            }
        }
        return predictions;
    }
    analyzeAst(code) {
        const results = [];
        let sourceFile;
        try {
            sourceFile = typescript_1.default.createSourceFile('analyze.tsx', code, typescript_1.default.ScriptTarget.Latest, true, typescript_1.default.ScriptKind.TSX);
        }
        catch {
            return results;
        }
        this.visitNode(sourceFile, code, results);
        return results;
    }
    visitNode(node, code, results) {
        if (typescript_1.default.isBinaryExpression(node) && node.operatorToken.kind === typescript_1.default.SyntaxKind.EqualsToken) {
            const lhs = node.left;
            const rhs = node.right;
            if (typescript_1.default.isPropertyAccessExpression(lhs) && lhs.name.text === 'innerHTML') {
                const line = typescript_1.default.getLineAndCharacterOfPosition(node.getSourceFile(), node.getStart()).line + 1;
                if (!results.some((r) => r.type === 'xss' && r.line === line)) {
                    results.push({
                        type: 'xss',
                        line,
                        severity: 'critical',
                        message: 'Potential XSS vulnerability: direct innerHTML assignment',
                        sanitizedVersion: code.substring(0, node.getStart()) + 'textContent = DOMPurify.sanitize(' + rhs.getText() + ')' + code.substring(node.getEnd()),
                    });
                }
            }
        }
        if (typescript_1.default.isJsxAttribute(node) && typescript_1.default.isIdentifier(node.name) && node.name.text === 'dangerouslySetInnerHTML') {
            const line = typescript_1.default.getLineAndCharacterOfPosition(node.getSourceFile(), node.getStart()).line + 1;
            if (!results.some((r) => r.type === 'xss' && r.line === line)) {
                results.push({
                    type: 'xss',
                    line,
                    severity: 'critical',
                    message: 'Potential XSS vulnerability: dangerouslySetInnerHTML used',
                    sanitizedVersion: '// Use DOMPurify.sanitize() before setting innerHTML',
                });
            }
        }
        if (typescript_1.default.isVariableDeclaration(node) || typescript_1.default.isPropertyAssignment(node)) {
            const name = typescript_1.default.isVariableDeclaration(node) && typescript_1.default.isIdentifier(node.name) ? node.name.text
                : typescript_1.default.isPropertyAssignment(node) && typescript_1.default.isIdentifier(node.name) ? node.name.text : null;
            const value = typescript_1.default.isVariableDeclaration(node) ? node.initializer : node.initializer;
            if (name && value && typescript_1.default.isStringLiteral(value)) {
                const secretPatterns = [/^api[_-]?key$/i, /^secret$/i, /^password$/i, /^token$/i, /^(API_KEY|SECRET|PASSWORD|TOKEN)$/];
                const codeText = code.substring(0, node.getStart());
                const usesEnv = /process\.env/.test(codeText) || /import\.meta\.env/.test(codeText);
                if (!usesEnv && secretPatterns.some((p) => p.test(name))) {
                    const line = typescript_1.default.getLineAndCharacterOfPosition(node.getSourceFile(), node.getStart()).line + 1;
                    if (!results.some((r) => r.type === 'hardcoded_secret' && r.line === line)) {
                        results.push({
                            type: 'hardcoded_secret',
                            line,
                            severity: 'critical',
                            message: 'Hardcoded secret detected',
                            sanitizedVersion: '// FIX: Use environment variable: process.env.SECRET',
                        });
                    }
                }
            }
        }
        typescript_1.default.forEachChild(node, (child) => this.visitNode(child, code, results));
    }
    checkSQLInjection(line, lineNum) {
        if (/(?:SELECT|INSERT|UPDATE|DELETE)\s.*\$\{/.test(line) || /(?:SELECT|INSERT|UPDATE|DELETE)\s.*\+/.test(line)) {
            return {
                type: 'sql_injection',
                line: lineNum,
                severity: 'critical',
                message: 'Potential SQL injection: string interpolation in SQL query',
                sanitizedVersion: '// Use parameterized queries: db.query("SELECT * FROM users WHERE id = ?", [userId])',
            };
        }
        return null;
    }
    checkPathTraversal(line, lineNum) {
        if (/\.\.\//.test(line) && /fs\.|require\(|import\(/.test(line)) {
            return {
                type: 'path_traversal',
                line: lineNum,
                severity: 'high',
                message: 'Potential path traversal vulnerability',
                sanitizedVersion: '// Use path.resolve() and validate against allowed base directory',
            };
        }
        return null;
    }
    checkHardcodedSecret(line, lineNum) {
        const secretPatterns = [
            /(?:api[_-]?key|secret|password|token)\s*[:=]\s*['"][^'"]+['"]/i,
            /(?:API_KEY|SECRET|PASSWORD|TOKEN)\s*=\s*['"][^'"]+['"]/,
        ];
        for (const pattern of secretPatterns) {
            if (pattern.test(line) && !line.includes('process.env') && !line.includes('import.meta.env')) {
                return {
                    type: 'hardcoded_secret',
                    line: lineNum,
                    severity: 'critical',
                    message: 'Hardcoded secret detected',
                    sanitizedVersion: '// FIX: Use environment variable: process.env.SECRET',
                };
            }
        }
        return null;
    }
}
exports.SecurityPredictor = SecurityPredictor;
//# sourceMappingURL=security-predictor.js.map