import { corrigirPontuacaoECodigo, normalizarFimDeLinha, normalizarNewlinesFinais, removerBom } from './commons.js';
const SQL_KEYWORDS = new Set(['select', 'from', 'where', 'insert', 'into', 'values', 'update', 'set', 'delete', 'create', 'table', 'drop', 'alter', 'add', 'column', 'index', 'join', 'left', 'right', 'inner', 'outer', 'on', 'and', 'or', 'not', 'in', 'is', 'null', 'as', 'order', 'by', 'group', 'having', 'limit', 'offset', 'union', 'all', 'distinct', 'case', 'when', 'then', 'else', 'end', 'exists', 'between', 'like', 'asc', 'desc', 'primary', 'key', 'foreign', 'references', 'constraint', 'default', 'check', 'unique', 'if', 'begin', 'commit', 'rollback', 'transaction', 'grant', 'revoke', 'with', 'recursive', 'over', 'partition', 'window', 'returning', 'cascade', 'restrict', 'no', 'action', 'using', 'cross', 'natural', 'full', 'replace', 'view', 'trigger', 'function', 'procedure', 'declare', 'fetch', 'cursor', 'open', 'close', 'deallocate']);
const MAJOR_CLAUSE_KEYWORDS = new Set(['SELECT', 'FROM', 'WHERE', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP', 'ALTER', 'ORDER BY', 'GROUP BY', 'HAVING', 'LIMIT', 'OFFSET', 'UNION', 'SET', 'VALUES', 'INTO', 'BEGIN', 'COMMIT', 'ROLLBACK', 'WITH', 'RETURNING']);
const JOIN_KEYWORDS = new Set(['JOIN', 'LEFT', 'RIGHT', 'INNER', 'OUTER', 'CROSS', 'NATURAL', 'FULL']);
function tokenizeSql(src) {
    const tokens = [];
    let indice = 0;
    while (indice < src.length) {
        if (src[indice] === '-' && src[indice + 1] === '-') {
            const end = src.indexOf('\n', indice);
            tokens.push({
                type: 'comment',
                value: end === -1 ? src.slice(indice) : src.slice(indice, end)
            });
            indice = end === -1 ? src.length : end;
            continue;
        }
        if (src[indice] === '/' && src[indice + 1] === '*') {
            const end = src.indexOf('*/', indice + 2);
            tokens.push({
                type: 'comment',
                value: end === -1 ? src.slice(indice) : src.slice(indice, end + 2)
            });
            indice = end === -1 ? src.length : end + 2;
            continue;
        }
        if (src[indice] === "'" || src[indice] === '"') {
            const delimitadorString = src[indice];
            let posAtual = indice + 1;
            while (posAtual < src.length && src[posAtual] !== delimitadorString) {
                if (src[posAtual] === '\\')
                    posAtual++;
                posAtual++;
            }
            tokens.push({
                type: 'string',
                value: src.slice(indice, posAtual + 1)
            });
            indice = posAtual + 1;
            continue;
        }
        if (/\d/.test(src[indice] ?? '') && (indice === 0 || !/\w/.test(src[indice - 1] ?? ''))) {
            let posAtual = indice;
            while (posAtual < src.length && /[\d.]/.test(src[posAtual] ?? ''))
                posAtual++;
            tokens.push({
                type: 'number',
                value: src.slice(indice, posAtual)
            });
            indice = posAtual;
            continue;
        }
        if (/[a-zA-Z_]/.test(src[indice] ?? '')) {
            let posAtual = indice;
            while (posAtual < src.length && /[\w]/.test(src[posAtual] ?? ''))
                posAtual++;
            const word = src.slice(indice, posAtual);
            tokens.push({
                type: SQL_KEYWORDS.has(word.toLowerCase()) ? 'keyword' : 'ident',
                value: word
            });
            indice = posAtual;
            continue;
        }
        if (/[=<>!+\-*/%&|^~]/.test(src[indice] ?? '')) {
            let posAtual = indice;
            while (posAtual < src.length && /[=<>!+\-*/%&|^~]/.test(src[posAtual] ?? ''))
                posAtual++;
            tokens.push({
                type: 'op',
                value: src.slice(indice, posAtual)
            });
            indice = posAtual;
            continue;
        }
        if (/[(),.;:]/.test(src[indice] ?? '')) {
            tokens.push({
                type: 'punct',
                value: src[indice] ?? ''
            });
            indice++;
            continue;
        }
        if (/\s/.test(src[indice] ?? '')) {
            let posAtual = indice;
            while (posAtual < src.length && /\s/.test(src[posAtual] ?? ''))
                posAtual++;
            tokens.push({
                type: 'ws',
                value: src.slice(indice, posAtual)
            });
            indice = posAtual;
            continue;
        }
        indice++;
    }
    return tokens;
}
export function formatarSqlMinimo(code) {
    const normalized = normalizarFimDeLinha(removerBom(code));
    const tokens = tokenizeSql(normalized);
    const out = [];
    let indent = 0;
    let lineStart = true;
    let inSelectClause = false;
    const pushIndent = () => '  '.repeat(indent);
    const peekKeyword = (from) => {
        for (let chave = from + 1; chave < tokens.length; chave++) {
            if (tokens[chave]?.type === 'ws')
                continue;
            const tk = tokens[chave];
            if (tk?.type === 'keyword')
                return String(tk.value).toUpperCase();
            return null;
        }
        return null;
    };
    for (let textoTitulo = 0; textoTitulo < tokens.length; textoTitulo++) {
        const tok = tokens[textoTitulo];
        if (!tok)
            continue;
        if (tok.type === 'comment') {
            if (!lineStart)
                out.push('\n');
            out.push(`${pushIndent()}${tok.value.trim()}`);
            out.push('\n');
            lineStart = true;
            continue;
        }
        if (tok.type === 'ws')
            continue;
        if (tok.type === 'keyword') {
            const upper = tok.value.toUpperCase();
            if (upper === 'ORDER' || upper === 'GROUP') {
                const next = peekKeyword(textoTitulo);
                if (next === 'BY') {
                    inSelectClause = false;
                    if (!lineStart)
                        out.push('\n');
                    out.push(`${pushIndent()}${upper} BY`);
                    lineStart = false;
                    for (let chave = textoTitulo + 1; chave < tokens.length; chave++) {
                        if (tokens[chave]?.type === 'ws')
                            continue;
                        const tk = tokens[chave];
                        if (tk?.type === 'keyword' && String(tk.value).toUpperCase() === 'BY') {
                            textoTitulo = chave;
                            break;
                        }
                        break;
                    }
                    continue;
                }
            }
            if (MAJOR_CLAUSE_KEYWORDS.has(upper)) {
                if (upper === 'FROM' || upper === 'WHERE' || upper === 'HAVING' || upper === 'LIMIT' || upper === 'OFFSET' || upper === 'SET' || upper === 'RETURNING') {
                    inSelectClause = false;
                }
                if (!lineStart)
                    out.push('\n');
                out.push(`${pushIndent()}${upper}`);
                lineStart = false;
                if (upper === 'SELECT')
                    inSelectClause = true;
                continue;
            }
            if (JOIN_KEYWORDS.has(upper)) {
                inSelectClause = false;
                if (!lineStart)
                    out.push('\n');
                out.push(`${pushIndent()}${upper}`);
                lineStart = false;
                continue;
            }
            if (upper === 'AND' || upper === 'OR') {
                out.push('\n');
                out.push(`${pushIndent()}  ${upper}`);
                lineStart = false;
                continue;
            }
            if (upper === 'ON') {
                out.push(` ${upper}`);
                lineStart = false;
                continue;
            }
            if (lineStart) {
                out.push(`${pushIndent()}${upper}`);
            }
            else {
                out.push(` ${upper}`);
            }
            lineStart = false;
            continue;
        }
        if (tok.type === 'punct') {
            if (tok.value === '(') {
                out.push(' (');
                indent++;
                out.push('\n');
                lineStart = true;
                continue;
            }
            if (tok.value === ')') {
                indent = Math.max(0, indent - 1);
                out.push('\n');
                out.push(`${pushIndent()})`);
                lineStart = false;
                continue;
            }
            if (tok.value === ',') {
                if (inSelectClause) {
                    out.push(',\n');
                    lineStart = true;
                }
                else {
                    out.push(',');
                }
                continue;
            }
            if (tok.value === ';') {
                out.push(';\n');
                lineStart = true;
                inSelectClause = false;
                continue;
            }
            if (tok.value === '.') {
                out.push('.');
                continue;
            }
            out.push(tok.value);
            lineStart = false;
            continue;
        }
        if (lineStart) {
            out.push(`${pushIndent()}  ${tok.value}`);
        }
        else {
            out.push(` ${tok.value}`);
        }
        lineStart = false;
    }
    const raw = out.join('').replace(/\n{3,}/g, '\n\n').trimEnd();
    const { text: comPontuacao, stats } = corrigirPontuacaoECodigo(raw);
    const formatted = normalizarNewlinesFinais(comPontuacao);
    const baseline = normalizarNewlinesFinais(normalized);
    const anyChanged = formatted !== baseline;
    return {
        ok: true,
        parser: 'sql',
        formatted,
        changed: anyChanged,
        reason: anyChanged ? `estilo-tutanus-sql(punct:${stats.pontuacaoRepetida},space:${stats.espacamentoIncorreto},ops:${stats.operadoresRelacionais})` : 'normalizacao-basica'
    };
}
//# sourceMappingURL=sql.js.map