import fs from 'node:fs';
import path from 'node:path';
import { lerArquivoTexto } from '../../shared/persistence/index.js';
import { TUTANUS_ARQUIVOS, TUTANUS_DIRS } from '../registry/paths.js';
import { LIMITES_PADRAO } from './limites.js';
const TUTANUS_ESTADO = TUTANUS_DIRS.STATE;
const ZELADOR_ABANDONED = path.join(TUTANUS_ESTADO, 'abandonados');
export const configPadrao = {
    VERBOSE: false,
    LOG_LEVEL: 'info',
    DEV_MODE: process.env.NODE_ENV === 'development' || process.env.TUTANUS_DEV === 'true',
    AUTOANALISE_CONCURRENCY: 5,
    COMPACT_MODE: false,
    SCAN_ONLY: false,
    ANALISE_SCAN_ONLY: false,
    LOG_ESTRUTURADO: false,
    SAFE_MODE: process.env.VITEST ? false : process.env.TUTANUS_SAFE_MODE !== '0',
    ALLOW_PLUGINS: process.env.TUTANUS_ALLOW_PLUGINS === '1' || false,
    ALLOW_EXEC: process.env.TUTANUS_ALLOW_EXEC === '1' || false,
    ALLOW_MUTATE_FS: true,
    GUARDIAN_ENABLED: true,
    GUARDIAN_ENFORCE_PROTECTION: true,
    GUARDIAN_BASELINE: TUTANUS_ARQUIVOS.GUARDIAN_BASELINE,
    GUARDIAN_ALLOW_ADDS: false,
    GUARDIAN_ALLOW_CHG: false,
    GUARDIAN_ALLOW_DELS: false,
    REPORT_SILENCE_LOGS: false,
    SUPPRESS_PARCIAL_LOGS: false,
    REPORT_EXPORT_ENABLED: false,
    REPORT_OUTPUT_DIR: TUTANUS_DIRS.REPORTS,
    REPORT_EXPORT_FULL: false,
    REPORT_FRAGMENT_OCCURRENCES: 2000,
    REPORT_FRAGMENT_FILEENTRIES: 500,
    REPORT_FRAGMENT_SUMMARY_TOPN: 5,
    REPORT_STREAM_ENABLED: false,
    REPORT_STREAM_AUTO_THRESHOLD: 5000,
    REPORT_STREAM_MAX_OCCURRENCES_PER_SHARD: 5000,
    REPORT_STREAM_MAX_BYTES_PER_SHARD: 10 * 1024 * 1024,
    REPORT_STREAM_COMPRESS: true,
    RELATORIO_SAUDE_TABELA_ENABLED: true,
    RELATORIO_SAUDE_DETALHADO_VERBOSE: true,
    TUTANUS_STATE_DIR: TUTANUS_ESTADO,
    ZELADOR_ABANDONED_DIR: ZELADOR_ABANDONED,
    ZELADOR_PENDING_PATH: path.join(TUTANUS_ESTADO, 'pendentes.json'),
    ZELADOR_REACTIVATE_PATH: path.join(TUTANUS_ESTADO, 'reativar.json'),
    ZELADOR_HISTORY_PATH: path.join(TUTANUS_ESTADO, 'historico.json'),
    ZELADOR_REPORT_PATH: path.join(TUTANUS_ESTADO, 'poda-tutanus.md'),
    ZELADOR_GHOST_INACTIVITY_DAYS: 30,
    ZELADOR_LINE_THRESHOLD: 20,
    CLI_INCLUDE_PATTERNS: [],
    CLI_INCLUDE_GROUPS: [],
    CLI_EXCLUDE_PATTERNS: [],
    INCLUDE_EXCLUDE_RULES: {
        globalExcludeGlob: [
            '**/node_modules/**', 'scripts/**', '.pnpm/**', 'out/**', 'build/**', 'dist/**',
            'coverage/**', '**/.turbo/**', '**/.vercel/**', '**/.expo/**', '**/.parcel-cache/**',
            '.deprecados/**', '**/deprecados/**', '.pensando/**', '**/pensando/**',
            '**/.tutanus/**', 'tutanus/**',
            '**/*.log', '**/*.lock', 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml',
            '**/.git/**',
        ]
    },
    SCANNER_EXTENSOES_COM_AST: [
        '.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs',
        '.gradle', '.gradle.kts',
        '.py', '.pyx', '.pyi',
        '.php', '.phtml', '.php3', '.php4', '.php5', '.php7', '.php8',
        '.go',
        '.rs',
        '.html', '.htm', '.css', '.scss', '.sass',
        '.xml', '.svg', '.astro',
        '.sql', '.pgsql', '.mysql', '.sqlite',
        '.sh', '.bash', '.zsh', '.fish',
    ],
    VIGIA_TOP_N: 10,
    ANALISE_LIMITES: {
        FUNCOES_LONGAS: {
            MAX_LINHAS: LIMITES_PADRAO.CODIGO.MAX_LINHAS_FUNCAO,
            MAX_PARAMETROS: LIMITES_PADRAO.CODIGO.MAX_PARAMETROS_FUNCAO,
            MAX_ANINHAMENTO: LIMITES_PADRAO.CODIGO.MAX_ANINHAMENTO_IF
        },
        CODIGO_FRAGIL: {
            MAX_LINHAS_FUNCAO: LIMITES_PADRAO.CODIGO.MAX_LINHAS_FUNCAO,
            MAX_PARAMETROS: LIMITES_PADRAO.CODIGO.MAX_PARAMETROS_FUNCAO,
            MAX_NESTED_CALLBACKS: LIMITES_PADRAO.CODIGO.MAX_NESTED_CALLBACKS
        }
    },
    ANALISE_AST_CACHE_ENABLED: true,
    ANALISE_METRICAS_ENABLED: true,
    ANALISE_TIMEOUT_POR_ANALISTA_MS: 30000,
    ANALISE_METRICAS_HISTORICO_PATH: path.join(TUTANUS_ESTADO, 'historico-metricas', 'metricas-historico.json'),
    ANALISE_METRICAS_HISTORICO_MAX: 200,
    ANALISE_PRIORIZACAO_ENABLED: true,
    ANALISE_PRIORIZACAO_PESOS: {
        duracaoMs: 1,
        ocorrencias: 2,
        penalidadeReuso: 0.5
    },
    ANALISE_INCREMENTAL_ENABLED: false,
    ANALISE_INCREMENTAL_STATE_PATH: path.join(TUTANUS_ESTADO, 'incremental-analise.json'),
    ANALISE_INCREMENTAL_VERSION: 1,
    ANALISE_CACHE_ENABLED: true,
    ANALISE_CACHE_STATE_PATH: path.join(TUTANUS_ESTADO, 'analysis-cache.json'),
    ANALISE_CACHE_VERSION: 1,
    ANALISE_CACHE_TTL_MS: 86400000,
    WORKER_POOL_ENABLED: true,
    WORKER_POOL_MAX_WORKERS: 0,
    WORKER_POOL_BATCH_SIZE: 10,
    WORKER_POOL_AUTO_THRESHOLD: 50,
    PARSE_ERRO_AGRUPAR: true,
    PARSE_ERRO_MAX_POR_ARQUIVO: 1,
    PARSE_ERRO_FALHA: false,
    PERF_SNAPSHOT_DIR: path.join('docs', 'perf'),
    ESTRUTURA_TARGETS: {
        TESTS_RAIZ_DIR: 'src',
        SCRIPTS_DIR: path.posix.join('src', 'scripts'),
        CONFIG_DIR: 'config',
        TYPES_DIR: 'types',
        DOCS_FRAGMENTS_DIR: path.posix.join('docs', 'fragments')
    },
    conventions: {
        typesDirectory: path.posix.join('src', 'tipos')
    },
    nameConventions: {
        typesDirectory: 'tipos',
        testsDirectory: 'testes',
        docsDirectory: 'docs',
        srcDirectory: 'src',
        configDirectory: 'config',
        scriptsDirectory: 'scripts',
        distDirectory: 'dist',
        assetsDirectory: 'assets',
        utilsDirectory: 'utils',
        servicesDirectory: 'services',
        componentsDirectory: 'components',
        modelsDirectory: 'models',
        middlewareDirectory: 'middleware',
        routesDirectory: 'routes',
        controllersDirectory: 'controllers',
        viewsDirectory: 'views',
        stylesDirectory: 'styles',
        imagesDirectory: 'images',
        localesDirectory: 'locales'
    },
    detectorMarkdown: {
        checkProveniencia: true,
        checkLicenses: true,
        checkReferences: true,
        headerLines: 30,
        whitelist: {
            paths: [],
            patterns: [],
            dirs: []
        },
        whitelistMode: 'merge'
    },
    STRUCTURE_PLUGINS: [],
    STRUCTURE_AUTO_FIX: false,
    STRUCTURE_CONCURRENCY: 5,
    ESTRUTURA_CAMADAS: {},
    STRUCTURE_REVERSE_MAP_PATH: path.join(TUTANUS_ESTADO, 'mapa-reversao.json'),
    ESTRUTURA_PLANO_MAX_FILE_SIZE: 256 * 1024,
    ESTRUTURA_ARQUIVOS_RAIZ_MAX: 10,
    STATE_DIR: TUTANUS_ESTADO,
    ZELADOR_STATE_DIR: TUTANUS_ESTADO,
    rules: {},
    testPadroes: {
        files: ['**/*.test.*', '**/*.spec.*', 'test/**/*', 'tests/**/*', '**/__tests__/**'],
        excludeFromOrphanCheck: true,
        allowAnyType: false
    },
    LOCALE: 'pt'
};
export const config = structuredClone(configPadrao);
function ehObjetoPlano(valor) {
    return !!valor && typeof valor === 'object' && !Array.isArray(valor);
}
function mesclarProfundo(target, src, fonte, diffs, prefix = '') {
    for (const chave of Object.keys(src || {})) {
        if (chave === '__proto__' || chave === 'constructor' || chave === 'prototype')
            continue;
        const keyCaminho = prefix ? `${prefix}.${chave}` : chave;
        const srcVal = src[chave];
        const tgtVal = target[chave];
        if (ehObjetoPlano(srcVal) && ehObjetoPlano(tgtVal)) {
            mesclarProfundo(tgtVal, srcVal, fonte, diffs, keyCaminho);
        }
        else if (srcVal !== undefined) {
            if (tgtVal !== srcVal) {
                diffs[keyCaminho] = { from: tgtVal, to: srcVal, fonte };
            }
            target[chave] = srcVal;
        }
    }
}
function converterConfigSimplificada(config) {
    const resultado = { ...config };
    if (config.locale) {
        resultado.LOCALE = config.locale;
        delete resultado.locale;
    }
    else if (config.locales) {
        resultado.LOCALE = config.locales;
        delete resultado.locales;
    }
    if (Array.isArray(config.exclude)) {
        resultado.INCLUDE_EXCLUDE_RULES = {
            globalExcludeGlob: config.exclude,
            dirRules: {},
            defaultExcludes: null
        };
        delete resultado.exclude;
    }
    if (config.languages && typeof config.languages === 'object') {
        const langs = config.languages;
        resultado.languageSupport = {};
        const langPadroes = {
            javascript: { parser: 'babel', plugin: 'core' },
            typescript: { parser: 'babel', plugin: 'core' },
            html: { parser: 'htmlparser2', plugin: 'core' },
            css: { parser: 'css-tree', plugin: 'core' },
            scss: { parser: 'css-tree', plugin: 'core' },
            sass: { parser: 'css-tree', plugin: 'core' },
            xml: { parser: 'fast-xml-parser', plugin: 'core' },
            php: { parser: 'heuristic', plugin: 'core' },
            python: { parser: 'heuristic', plugin: 'core' },
            go: { parser: 'heuristic', plugin: 'core' },
            rust: { parser: 'heuristic', plugin: 'core' },
            sql: { parser: 'heuristic', plugin: 'core' },
            shell: { parser: 'heuristic', plugin: 'core' },
            svg: { parser: 'fast-xml-parser', plugin: 'core' },
            react: { parser: 'babel', plugin: 'core' },
            tailwind: { parser: 'heuristic', plugin: 'core' },
            astro: { parser: 'heuristic', plugin: 'core' },
            gradle: { parser: 'heuristic', plugin: 'core' },
        };
        for (const [lang, enabled] of Object.entries(langs)) {
            const defaults = langPadroes[lang];
            if (defaults) {
                resultado.languageSupport[lang] = {
                    enabled,
                    ...defaults
                };
            }
        }
        const enabledPlugins = ['core'];
        resultado.plugins = {
            enabled: enabledPlugins,
            autoload: true,
            registry: '@tutanus/plugins'
        };
        delete resultado.languages;
    }
    if (config.suppress && typeof config.suppress === 'object') {
        const suppress = config.suppress;
        if (Array.isArray(suppress.rules))
            resultado.suppressRules = suppress.rules;
        if (suppress.severity && typeof suppress.severity === 'object')
            resultado.suppressBySeverity = suppress.severity;
        if (Array.isArray(suppress.paths))
            resultado.suppressByPath = suppress.paths;
        if (Array.isArray(suppress.filePatterns))
            resultado.suppressByFilePattern = suppress.filePatterns;
        delete resultado.suppress;
    }
    return resultado;
}
function sincronizarIgnorados() {
    const dyn = (config.INCLUDE_EXCLUDE_RULES || {});
    const glob = Array.isArray(dyn.globalExcludeGlob) ? dyn.globalExcludeGlob : [];
    Array.from(new Set(glob.map(grupo => String(grupo))));
    const cfg = config;
    delete cfg.ZELADOR_IGNORE_PATTERNS;
    delete cfg.GUARDIAN_IGNORE_PATTERNS;
}
function carregarEnvConfig() {
    const resultado = {};
    const stack = [{
            obj: configPadrao,
            prefix: ''
        }];
    while (stack.length) {
        const popped = stack.pop();
        if (!popped)
            break;
        const { obj, prefix } = popped;
        for (const chave of Object.keys(obj)) {
            const keyCaminho = prefix ? `${prefix}.${chave}` : chave;
            const envNome = `TUTANUS_${keyCaminho.replace(/\./g, '_').toUpperCase()}`;
            const currentVal = obj[chave];
            if (ehObjetoPlano(currentVal)) {
                stack.push({ obj: currentVal, prefix: keyCaminho });
            }
            else {
                const rawEnv = process.env[envNome];
                if (rawEnv !== undefined) {
                    let val = rawEnv;
                    if (/^(true|false)$/i.test(rawEnv))
                        val = rawEnv.toLowerCase() === 'true';
                    else if (/^-?\d+(\.\d+)?$/.test(rawEnv))
                        val = Number(rawEnv);
                    atribuirPorCaminho(resultado, keyCaminho, val);
                }
            }
        }
    }
    return resultado;
}
function isPrototypePollutingKey(key) {
    return key === '__proto__' || key === 'constructor' || key === 'prototype';
}
function atribuirPorCaminho(base, keyCaminho, value) {
    const parts = keyCaminho.split('.');
    let cursor = base;
    for (let i = 0; i < parts.length - 1; i++) {
        const part = parts[i];
        if (isPrototypePollutingKey(part))
            return;
        let next = cursor[part];
        if (!ehObjetoPlano(next)) {
            next = {};
            cursor[part] = next;
        }
        cursor = next;
    }
    const lastKey = parts[parts.length - 1];
    if (isPrototypePollutingKey(lastKey))
        return;
    cursor[lastKey] = value;
}
const configRecord = () => config;
function sincronizarFlagsScan() {
    if (config.ANALISE_SCAN_ONLY && !config.SCAN_ONLY)
        config.SCAN_ONLY = true;
    else if (config.SCAN_ONLY && !config.ANALISE_SCAN_ONLY)
        config.ANALISE_SCAN_ONLY = true;
}
async function carregarConfigJSON(nome, diretorio) {
    try {
        const dir = diretorio || process.cwd();
        const caminho = path.join(dir, nome);
        const conteudo = await lerArquivoTexto(caminho);
        const json = conteudo?.trim() ? JSON.parse(conteudo) : null;
        if (json)
            return converterConfigSimplificada(json);
    }
    catch {
    }
    return null;
}
function carregarConfigJSONSync(nome) {
    try {
        const caminho = path.join(process.cwd(), nome);
        const conteudo = fs.readFileSync(caminho, 'utf-8');
        const json = conteudo?.trim() ? JSON.parse(conteudo) : null;
        if (json)
            return converterConfigSimplificada(json);
    }
    catch {
    }
    return null;
}
export async function inicializarConfigDinamica(overridesCli) {
    const diffs = {};
    for (const nome of ['tutanus.config.json', 'src/config.json']) {
        const arquivo = await carregarConfigJSON(nome);
        if (arquivo) {
            mesclarProfundo(configRecord(), arquivo, 'arquivo', diffs);
            break;
        }
    }
    const envCfg = carregarEnvConfig();
    if (Object.keys(envCfg).length)
        mesclarProfundo(configRecord(), envCfg, 'env', diffs);
    if (overridesCli && Object.keys(overridesCli).length)
        mesclarProfundo(configRecord(), overridesCli, 'cli', diffs);
    sincronizarFlagsScan();
    sincronizarIgnorados();
    config.__OVERRIDES__ = diffs;
    return diffs;
}
export function aplicarConfigParcial(partial) {
    const diffs = {};
    mesclarProfundo(configRecord(), partial, 'programatico', diffs);
    sincronizarFlagsScan();
    sincronizarIgnorados();
    config.__OVERRIDES__ = { ...(config.__OVERRIDES__ || {}), ...diffs };
    return diffs;
}
export function inicializarConfigSync() {
    const diffs = {};
    for (const nome of ['tutanus.config.json', 'src/config.json']) {
        const arquivo = carregarConfigJSONSync(nome);
        if (arquivo) {
            mesclarProfundo(configRecord(), arquivo, 'arquivo-sync', diffs);
            break;
        }
    }
    const envCfg = carregarEnvConfig();
    if (Object.keys(envCfg).length)
        mesclarProfundo(configRecord(), envCfg, 'env-sync', diffs);
    sincronizarFlagsScan();
    sincronizarIgnorados();
    config.__OVERRIDES__ = { ...(config.__OVERRIDES__ || {}), ...diffs };
    return diffs;
}
export async function carregarConfigDeDiretorio(diretorio) {
    for (const nome of ['tutanus.config.json', 'src/config.json']) {
        const convertido = await carregarConfigJSON(nome, diretorio);
        if (convertido) {
            const diffs = {};
            mesclarProfundo(configRecord(), convertido, 'repo-config', diffs);
            sincronizarIgnorados();
            config.__OVERRIDES__ = { ...(config.__OVERRIDES__ || {}), ...diffs };
            return true;
        }
    }
    return false;
}
if (!process.env.VITEST) {
    inicializarConfigSync();
}
if (!process.env.VITEST) {
    void inicializarConfigDinamica();
}
//# sourceMappingURL=config.js.map