import fs from 'node:fs';
import { createRequire } from 'node:module';
import path from 'node:path';
import { getSyntaxInfoForPath } from '../core/syntax-map.js';
import { normalizarFimDeLinha } from '../formatters/commons.js';
function isPrettierApi(value) {
    return typeof value === 'object' && value !== null && 'format' in value && typeof value.format === 'function' && 'resolveConfig' in value && typeof value.resolveConfig === 'function';
}
const prettierCache = new Map();
async function carregarPrettierDoProjeto(baseDir) {
    const base = baseDir || process.cwd();
    const cached = prettierCache.get(base);
    if (cached)
        return cached;
    const loader = (async () => {
        const tryImportPrettier = async (resolved) => {
            try {
                const mod = await import(resolved);
                const candidate = mod && typeof mod === 'object' && 'default' in mod ? mod.default : mod;
                if (!candidate || !isPrettierApi(candidate)) {
                    return null;
                }
                return candidate;
            }
            catch {
                return null;
            }
        };
        const tryResolveFrom = async (req) => {
            try {
                const resolved = req.resolve('prettier');
                return await tryImportPrettier(resolved);
            }
            catch {
                return null;
            }
        };
        const fromProjectPkg = await tryResolveFromProjectPkg(base, tryResolveFrom);
        if (fromProjectPkg)
            return fromProjectPkg;
        {
            const api = await tryResolveFrom(createRequire(import.meta.url));
            if (api)
                return api;
        }
        const feedbackDir = process.env.TUTANUS_PRETTIER_FEEDBACK_DIR || path.join(base, 'feedback', 'prettier');
        const fromFeedback = await tryResolveFromFeedbackDir(feedbackDir, tryImportPrettier);
        if (fromFeedback)
            return fromFeedback;
        return null;
    })();
    prettierCache.set(base, loader);
    return loader;
}
async function tryResolveFromProjectPkg(base, tryResolveFrom) {
    try {
        const projectPkg = path.join(base, 'package.json');
        fs.statSync(projectPkg);
        return await tryResolveFrom(createRequire(projectPkg));
    }
    catch {
        return null;
    }
}
async function tryResolveFromFeedbackDir(feedbackDir, tryImportPrettier) {
    try {
        const feedbackPkg = path.join(feedbackDir, 'package.json');
        fs.statSync(feedbackPkg);
        const candidates = [path.join(feedbackDir, 'index.mjs'), path.join(feedbackDir, 'index.cjs')];
        for (const caminho of candidates) {
            try {
                fs.statSync(caminho);
            }
            catch {
                continue;
            }
            const api = await tryImportPrettier(caminho);
            if (api)
                return api;
        }
    }
    catch {
    }
    return null;
}
function inferPrettierParser(relPath, code) {
    const info = getSyntaxInfoForPath(relPath ?? '');
    if (!info)
        return null;
    if (!info.formatavel)
        return null;
    const rp = (relPath ?? '').toLowerCase();
    if (rp.endsWith('.json')) {
        const src = code ?? '';
        const normalized = normalizarFimDeLinha(src);
        const hasComments = /(^|\n)\s*\/\//.test(normalized) || /(^|\n)\s*\/\*/.test(normalized);
        return hasComments ? 'jsonc' : 'json';
    }
    return info.parser ?? null;
}
export async function formatarComPrettierProjeto(params) {
    const baseDir = params.baseDir || process.cwd();
    const relPath = params.relPath;
    const absCaminho = path.resolve(baseDir, relPath);
    const prettier = await carregarPrettierDoProjeto(baseDir);
    if (!prettier) {
        return {
            ok: true,
            parser: 'unknown',
            formatted: params.code,
            changed: false,
            reason: 'prettier-nao-disponivel'
        };
    }
    const parser = inferPrettierParser(relPath, params.code);
    if (!parser) {
        return {
            ok: true,
            parser: 'unknown',
            formatted: params.code,
            changed: false,
            reason: 'prettier-parser-desconhecido'
        };
    }
    try {
        const resolvedConfig = await prettier.resolveConfig(absCaminho, {
            editorconfig: true
        });
        const inferSingleQuote = (src) => {
            try {
                const singles = (src.match(/'/g) || []).length;
                const doubles = (src.match(/"/g) || []).length;
                return singles > doubles;
            }
            catch {
                return false;
            }
        };
        const options = {
            ...(resolvedConfig || {}),
            filepath: absCaminho,
            parser
        };
        if (!resolvedConfig || !Object.prototype.hasOwnProperty.call(resolvedConfig, 'singleQuote')) {
            if (parser === 'babel' || parser === 'typescript') {
                options.singleQuote = inferSingleQuote(params.code);
            }
        }
        const out = await prettier.format(params.code, options);
        const formatted = String(out);
        return {
            ok: true,
            parser: 'code',
            formatted,
            changed: formatted !== params.code,
            reason: 'prettier-projeto'
        };
    }
    catch (erro) {
        const msg = erro instanceof Error ? erro.message : String(erro);
        return {
            ok: false,
            parser: 'code',
            error: msg
        };
    }
}
//# sourceMappingURL=prettier.js.map