import { messages } from '../../../core/messages/index.js';
import { createLineLookup } from '../../../shared/helpers/index.js';
import { criarAnalista, criarOcorrencia } from '../../../types/index.js';
const disableEnv = process.env.TUTANUS_DISABLE_PLUGIN_PHP === '1';
function isPhpFile(relPath) {
    return /\.(php|phtml|php3|php4|php5|php7|php8)$/i.test(relPath);
}
function warn(message, relPath, line, nivel) {
    return criarOcorrencia({
        relPath,
        mensagem: message,
        linha: line,
        nivel: nivel ?? messages.SeverityNiveis.warning,
        origem: messages.AnalystOrigens.php,
        tipo: messages.AnalystTipos.php
    });
}
function collectPhpIssues(src, relPath) {
    const ocorrencias = [];
    const lineOf = createLineLookup(src).lineAt;
    const scanWithoutStrings = src.replace(/['"`][^'"]*['"`]/g, '""');
    for (const match of scanWithoutStrings.matchAll(/\b(?:mysql|mysqli|sqlite|pg)_query\s*\(\s*\$[^)]*(?:\$|\.)/gi)) {
        const line = lineOf(match.index);
        ocorrencias.push(warn(messages.PhpMensagens.sqlInjection, relPath, line, messages.SeverityNiveis.error));
    }
    for (const match of scanWithoutStrings.matchAll(/\beval\s*\(/gi)) {
        const line = lineOf(match.index);
        ocorrencias.push(warn(messages.PhpMensagens.evalUsage, relPath, line, messages.SeverityNiveis.error));
    }
    for (const match of scanWithoutStrings.matchAll(/\bassert\s*\(\s*['"]/gi)) {
        const line = lineOf(match.index);
        ocorrencias.push(warn(messages.PhpMensagens.assertString, relPath, line, messages.SeverityNiveis.error));
    }
    for (const match of scanWithoutStrings.matchAll(/\bunserialize\s*\(/gi)) {
        const line = lineOf(match.index);
        ocorrencias.push(warn(messages.PhpMensagens.unserializeUsage, relPath, line, messages.SeverityNiveis.error));
    }
    for (const match of scanWithoutStrings.matchAll(/\bextract\s*\(/gi)) {
        const line = lineOf(match.index);
        ocorrencias.push(warn(messages.PhpMensagens.extractUsage, relPath, line, messages.SeverityNiveis.error));
    }
    for (const match of scanWithoutStrings.matchAll(/\bfile_get_contents\s*\(\s*['"](?:https?:\/\/)/gi)) {
        const line = lineOf(match.index);
        ocorrencias.push(warn(messages.PhpMensagens.urlFetch, relPath, line));
    }
    for (const match of scanWithoutStrings.matchAll(/\b(?:system|exec|shell_exec|passthru|popen|proc_open)\s*\(/gi)) {
        const line = lineOf(match.index);
        ocorrencias.push(warn(messages.PhpMensagens.commandExecution, relPath, line, messages.SeverityNiveis.error));
    }
    for (const match of scanWithoutStrings.matchAll(/\$_REQUEST\b/gi)) {
        const line = lineOf(match.index);
        ocorrencias.push(warn(messages.PhpMensagens.requestUsage, relPath, line));
    }
    for (const match of scanWithoutStrings.matchAll(/(?:password|secret|api[_-]?key|token|credential|db_password|db_user)\s*(?::\s*|=>\s*|=\s*["'`])([^"'`\s]{4,})/gi)) {
        const line = lineOf(match.index);
        ocorrencias.push(warn(messages.PhpMensagens.hardcodedSecret, relPath, line, messages.SeverityNiveis.error));
    }
    for (const match of scanWithoutStrings.matchAll(/\bmysql_\w+\s*\(/gi)) {
        const line = lineOf(match.index);
        ocorrencias.push(warn(messages.PhpMensagens.deprecatedMysql, relPath, line));
    }
    if (/^<\?[^=phHP\r\n]/m.test(src)) {
        ocorrencias.push(warn(messages.PhpMensagens.shortOpenTag, relPath, 1));
    }
    for (const match of src.matchAll(/@\s*(?:mkdir|file_put_contents|fopen|include|require|unlink|copy|rename|move_uploaded_file|file_get_contents)\s*\(/g)) {
        const line = lineOf(match.index);
        ocorrencias.push(warn(messages.PhpMensagens.errorSuppression, relPath, line));
    }
    const funcMatches = src.matchAll(/(?:^|\n)\s*(?:public|private|protected|static)?\s*function\s+\w+\s*\([^)]*\)\s*(?::\s*\w+)?\s*\{/g);
    for (const funcMatch of funcMatches) {
        const startIdx = (funcMatch.index ?? 0) + (funcMatch[0]?.length ?? 0);
        let braceCount = 1;
        let endIdx = startIdx;
        for (let i = startIdx; i < src.length && braceCount > 0; i++) {
            if (src[i] === '{')
                braceCount++;
            if (src[i] === '}')
                braceCount--;
            endIdx = i;
        }
        const body = src.slice(startIdx, endIdx);
        const lines = body.split('\n').length;
        if (lines > 60) {
            const line = lineOf(funcMatch.index ?? 0);
            ocorrencias.push(warn(messages.PhpMensagens.longFunction, relPath, line));
        }
    }
    for (const match of src.matchAll(/\b(?:var_dump|dump|print_r|die|exit)\s*\(/g)) {
        const line = lineOf(match.index);
        if (!relPath.includes('tests/') && !relPath.includes('debug/')) {
            ocorrencias.push(warn(messages.PhpMensagens.debugOutput, relPath, line));
        }
    }
    for (const match of scanWithoutStrings.matchAll(/\bfunction\s+([a-z][a-zA-Z0-9]*)\s*\(/g)) {
        const funcName = match[1] ?? '';
        if (/^[a-z]+[A-Z]/.test(funcName)) {
            const line = lineOf(match.index);
            ocorrencias.push(warn(messages.PhpMensagens.camelCaseFunction, relPath, line, messages.SeverityNiveis.suggestion));
        }
    }
    return ocorrencias;
}
export const analistaPhp = criarAnalista({
    nome: 'analista-php',
    categoria: 'linguagem',
    descricao: 'Analisa código PHP em busca de segurança, boas práticas e qualidade com parser dedicado.',
    global: false,
    test: (relPath) => isPhpFile(relPath),
    aplicar: async (src, relPath) => {
        if (disableEnv)
            return null;
        const msgs = collectPhpIssues(src, relPath);
        return msgs.length ? msgs : null;
    }
});
//# sourceMappingURL=analyst-php.js.map