import path from 'node:path';
import { normalizePath } from './index.js';
import { lerEstado } from '../persistence/index.js';
export const CATEGORIAS_PADRAO = {
    controller: 'controllers',
    controllers: 'controllers',
    webhook: 'webhooks',
    webhooks: 'webhooks',
    cliente: 'clients',
    client: 'clients',
    service: 'services',
    repository: 'repositories',
    config: 'config',
    test: '__tests__',
    spec: '__tests__',
    type: 'types',
    types: 'types',
    handler: 'handlers',
    entity: 'domain/entities',
    entities: 'domain/entities',
    'value-object': 'domain/value-objects',
    'value-objects': 'domain/value-objects',
    'domain-service': 'domain/services',
    'domain-services': 'domain/services',
    'use-case': 'application/use-cases',
    'use-cases': 'application/use-cases',
    interactor: 'application/use-cases',
    interactors: 'application/use-cases',
    port: 'application/ports',
    ports: 'application/ports',
    dto: 'application/dto',
    dtos: 'application/dto',
    presenter: 'presentation/presenters',
    presenters: 'presentation/presenters',
    gateway: 'infrastructure/gateways',
    gateways: 'infrastructure/gateways',
    event: 'infrastructure/events',
    events: 'infrastructure/events',
    consumer: 'infrastructure/consumers',
    consumers: 'infrastructure/consumers',
    producer: 'infrastructure/producers',
    producers: 'infrastructure/producers',
    messaging: 'infrastructure/messaging',
    scheduler: 'infrastructure/schedulers',
    scheduled: 'infrastructure/schedulers',
    job: 'infrastructure/jobs',
    jobs: 'infrastructure/jobs',
    worker: 'infrastructure/workers',
    workers: 'infrastructure/workers',
    adapter: 'infrastructure/adapters',
    adapters: 'infrastructure/adapters',
    factory: 'domain/factories',
    factories: 'domain/factories',
    'domain-event': 'domain/events',
    'domain-events': 'domain/events',
    specification: 'domain/specifications',
    specifications: 'domain/specifications',
    policy: 'domain/policies',
    policies: 'domain/policies'
};
export const PADRAO_OPCOES = {
    raizCodigo: 'src',
    criarSubpastasPorEntidade: true,
    apenasCategoriasConfiguradas: true,
    estiloPreferido: 'kebab',
    categoriasMapa: {},
    ignorarPastas: ['node_modules', '.git', 'dist', 'build', 'coverage', '.tutanus']
};
export const PRESETS = {
    tutanus: {
        nome: 'tutanus',
        criarSubpastasPorEntidade: false,
        apenasCategoriasConfiguradas: false,
        categoriasMapa: {
            ...CATEGORIAS_PADRAO
        },
        ignorarPastas: [...PADRAO_OPCOES.ignorarPastas, 'tests', 'tests/fixtures', 'src/analistas', 'src/arquitetos', 'src/relatorios', 'src/guardian', 'src/nucleo', 'src/cli', 'src/zeladores']
    },
    'node-community': {
        nome: 'node-community',
        criarSubpastasPorEntidade: false,
        apenasCategoriasConfiguradas: false,
        categoriasMapa: {
            ...CATEGORIAS_PADRAO
        }
    },
    'ts-lib': {
        nome: 'ts-lib',
        criarSubpastasPorEntidade: false,
        apenasCategoriasConfiguradas: false,
        categoriasMapa: {
            ...CATEGORIAS_PADRAO
        }
    },
    'clean-arch': {
        nome: 'clean-arch',
        criarSubpastasPorEntidade: false,
        apenasCategoriasConfiguradas: false,
        categoriasMapa: {
            ...CATEGORIAS_PADRAO,
            entity: 'domain/entities',
            'value-object': 'domain/value-objects',
            'use-case': 'application/use-cases',
            port: 'application/ports',
            dto: 'application/dto',
            controller: 'presentation/controllers',
            presenter: 'presentation/presenters',
            repository: 'infrastructure/repositories',
            adapter: 'infrastructure/adapters',
            gateway: 'infrastructure/gateways',
            event: 'infrastructure/events',
            consumer: 'infrastructure/consumers',
            producer: 'infrastructure/producers',
            job: 'infrastructure/jobs',
            worker: 'infrastructure/workers'
        },
        ignorarPastas: ['node_modules', '.git', 'dist', 'build', 'coverage', '.tutanus', 'tests', 'test']
    },
    'microservices': {
        nome: 'microservices',
        criarSubpastasPorEntidade: true,
        apenasCategoriasConfiguradas: true,
        categoriasMapa: {
            ...CATEGORIAS_PADRAO,
            gateway: 'infrastructure/gateways',
            event: 'infrastructure/events',
            consumer: 'infrastructure/consumers',
            producer: 'infrastructure/producers',
            messaging: 'infrastructure/messaging',
            job: 'infrastructure/jobs',
            worker: 'infrastructure/workers',
            health: 'infrastructure/monitoring',
            metric: 'infrastructure/monitoring',
            monitor: 'infrastructure/monitoring'
        }
    }
};
export function deveIgnorar(rel, ignorar) {
    const norm = normalizePath(rel);
    return ignorar.some(raw => {
        const pat = normalizePath(raw);
        if (!pat)
            return false;
        if (norm === pat)
            return true;
        if (norm.startsWith(`${pat}/`))
            return true;
        if (norm.endsWith(`/${pat}`))
            return true;
        if (norm.includes(`/${pat}/`))
            return true;
        if (!pat.includes('/')) {
            const segs = norm.split('/');
            if (segs.includes(pat))
                return true;
        }
        return false;
    });
}
export function parseNomeArquivo(baseNome) {
    const semExt = baseNome.replace(/\.[^.]+$/i, '');
    const lower = semExt.toLowerCase();
    const CATS = new Set(Object.keys(CATEGORIAS_PADRAO).map(elem => elem.toLowerCase()));
    const dotMatch = /^(?<ent>[\w-]+)\.(?<cat>[\w-]+)$/.exec(semExt);
    if (dotMatch?.groups) {
        const cat = dotMatch.groups.cat.toLowerCase();
        if (CATS.has(cat))
            return {
                entidade: dotMatch.groups.ent,
                categoria: cat
            };
    }
    const kebabMatch = /^(?<ent>[\w-]+)-(?<cat>[\w-]+)$/.exec(lower);
    if (kebabMatch?.groups) {
        const cat = kebabMatch.groups.cat.toLowerCase();
        if (CATS.has(cat))
            return {
                entidade: kebabMatch.groups.ent,
                categoria: cat
            };
    }
    const camelMatch = /^(?<ent>[A-Za-z][A-Za-z0-9]*?)(?<cat>Controller|Webhook|Cliente|Client|Service|Repository)$/.exec(semExt);
    if (camelMatch?.groups)
        return {
            entidade: camelMatch.groups.ent,
            categoria: camelMatch.groups.cat.toLowerCase()
        };
    const tokens = ['controller', 'controllers', 'webhook', 'webhooks', 'cliente', 'client', 'service', 'repository'];
    for (const tk of tokens) {
        if (lower.endsWith(`-${tk}`) || lower.endsWith(`.${tk}`)) {
            const entidade = lower.replace(new RegExp(`[.-]${tk}$`), '');
            return {
                entidade: entidade || null,
                categoria: tk
            };
        }
    }
    return {
        entidade: null,
        categoria: null
    };
}
export function destinoPara(relPath, raizCodigo, criarSubpastasPorEntidade, apenasCategoriasConfiguradas, categoriasMapa) {
    const baseNome = path.posix.basename(normalizePath(relPath));
    const { entidade, categoria } = parseNomeArquivo(baseNome);
    if (!categoria)
        return {
            destinoDir: null
        };
    const normCat = categoria.toLowerCase();
    const pastaMapeada = categoriasMapa[normCat];
    if (!pastaMapeada && apenasCategoriasConfiguradas) {
        return {
            destinoDir: null,
            motivo: `categoria ${categoria} não configurada`
        };
    }
    const pastaFinal = pastaMapeada || (normCat.endsWith('s') ? normCat : `${normCat}s`);
    if (criarSubpastasPorEntidade && entidade) {
        const ent = entidade.toString().replace(/[^a-z0-9-]/gi, '').toLowerCase();
        const dir = path.posix.join(raizCodigo, 'domains', ent, pastaFinal);
        return {
            destinoDir: dir,
            motivo: `categoria ${categoria} organizada por entidade ${ent}`
        };
    }
    return {
        destinoDir: path.posix.join(raizCodigo, pastaFinal),
        motivo: `categoria ${categoria} organizada por camada`
    };
}
export function normalizarRel(relPath) {
    return normalizePath(relPath);
}
export async function carregarConfigEstrategia(baseDir, overrides) {
    const caminho = path.join(baseDir, '.tutanus', 'estrutura.json');
    const lido = await lerEstado(caminho);
    const cfgObj = lido && !Array.isArray(lido) && typeof lido === 'object' ? lido : {};
    const nomePreset = overrides?.preset ?? cfgObj['preset'];
    const preset = nomePreset && PRESETS[nomePreset]?.nome ? PRESETS[nomePreset] : undefined;
    const base = {
        raizCodigo: 'src',
        criarSubpastasPorEntidade: true,
        apenasCategoriasConfiguradas: true,
        categoriasMapa: CATEGORIAS_PADRAO,
        ignorarPastas: ['node_modules', '.git', 'dist', 'build', 'coverage', '.tutanus'],
        estiloPreferido: PADRAO_OPCOES.estiloPreferido ?? 'kebab'
    };
    aplicarParcialConfig(preset, base);
    aplicarParcialConfig(cfgObj, base);
    aplicarParcialConfig(overrides, base);
    if (!base.apenasCategoriasConfiguradas) {
        base.categoriasMapa = {
            ...CATEGORIAS_PADRAO,
            ...base.categoriasMapa
        };
    }
    return base;
}
function aplicarParcialConfig(src, base) {
    if (!src)
        return;
    if (typeof src.raizCodigo === 'string')
        base.raizCodigo = src.raizCodigo;
    if (typeof src.criarSubpastasPorEntidade === 'boolean')
        base.criarSubpastasPorEntidade = src.criarSubpastasPorEntidade;
    if (typeof src.apenasCategoriasConfiguradas === 'boolean')
        base.apenasCategoriasConfiguradas = src.apenasCategoriasConfiguradas;
    if (typeof src.estiloPreferido === 'string')
        base.estiloPreferido = src.estiloPreferido;
    if (src.categoriasMapa && typeof src.categoriasMapa === 'object') {
        base.categoriasMapa = {
            ...base.categoriasMapa,
            ...src.categoriasMapa
        };
    }
    if (Array.isArray(src.ignorarPastas)) {
        base.ignorarPastas = Array.from(new Set([...base.ignorarPastas, ...src.ignorarPastas]));
    }
}
//# sourceMappingURL=structure.js.map