/**
 * clean-auto-imports.js
 *
 * Remove imports manuais redundantes de arquivos .vue e .js,
 * considerando que o projeto usa:
 *   - unplugin-auto-import  → auto-importa APIs do Vue
 *   - unplugin-vue-components + PrimeVueResolver → auto-importa componentes PrimeVue nos templates
 *
 * Uso: node scripts/clean-auto-imports.js
 * Dry-run (sem escrever): node scripts/clean-auto-imports.js --dry-run
 */

import { readdir, readFile, writeFile } from 'node:fs/promises';
import { join, extname, relative, basename } from 'node:path';
import { fileURLToPath } from 'node:url';

const isDryRun = process.argv.includes('--dry-run');

// ─── Lista exata do auto-imports.d.ts gerado pelo unplugin-auto-import ────────
const VUE_AUTO_IMPORTS = new Set([
    'EffectScope', 'computed', 'createApp', 'customRef', 'defineAsyncComponent',
    'defineComponent', 'effectScope', 'getCurrentInstance', 'getCurrentScope',
    'getCurrentWatcher', 'h', 'inject', 'isProxy', 'isReactive', 'isReadonly',
    'isRef', 'isShallow', 'markRaw', 'nextTick', 'onActivated', 'onBeforeMount',
    'onBeforeUnmount', 'onBeforeUpdate', 'onDeactivated', 'onErrorCaptured',
    'onMounted', 'onRenderTracked', 'onRenderTriggered', 'onScopeDispose',
    'onServerPrefetch', 'onUnmounted', 'onUpdated', 'onWatcherCleanup', 'provide',
    'reactive', 'readonly', 'ref', 'resolveComponent', 'shallowReactive',
    'shallowReadonly', 'shallowRef', 'toRaw', 'toRef', 'toRefs', 'toValue',
    'triggerRef', 'unref', 'useAttrs', 'useCssModule', 'useCssVars', 'useId',
    'useModel', 'useSlots', 'useTemplateRef', 'watch', 'watchEffect',
    'watchPostEffect', 'watchSyncEffect',
    // Tipos re-exportados (import type { ... } from 'vue')
    'Component', 'Slot', 'Slots', 'ComponentPublicInstance', 'ComputedRef',
    'DirectiveBinding', 'ExtractDefaultPropTypes', 'ExtractPropTypes',
    'ExtractPublicPropTypes', 'InjectionKey', 'PropType', 'Ref', 'ShallowRef',
    'MaybeRef', 'MaybeRefOrGetter', 'VNode', 'WritableComputedRef',
]);

// ─── Paths do PrimeVue que NÃO são componentes (serviços, plugins, diretivas) ─
const PRIMEVUE_KEEP_PATHS = new Set([
    'primevue/config',
    'primevue/confirmationservice',
    'primevue/toastservice',
    'primevue/dialogservice',
    'primevue/useconfirm',
    'primevue/usetoast',
    'primevue/usedynamicdialog',
    'primevue/ripple',
    'primevue/tooltip',
    'primevue/focustrap',
    'primevue/styleclass',
    'primevue/badgedirective',
    'primevue/animateonscroll',
    'primevue/passthrough',
    'primevue/useStyle',
]);

// ─── Arquivos a ignorar ────────────────────────────────────────────────────────
const SKIP_FILES = new Set(['main.js', 'main.ts']);

// ─────────────────────────────────────────────────────────────────────────────

async function getAllFiles(dir) {
    const results = [];
    const entries = await readdir(dir, { withFileTypes: true });

    for (const entry of entries) {
        const fullPath = join(dir, entry.name);
        if (entry.isDirectory()) {
            if (!['node_modules', '.git', 'dist', '.nuxt', 'public'].includes(entry.name)) {
                results.push(...await getAllFiles(fullPath));
            }
        } else {
            const ext = extname(entry.name);
            if (['.vue', '.js', '.mjs'].includes(ext) && !SKIP_FILES.has(entry.name)) {
                results.push(fullPath);
            }
        }
    }
    return results;
}

/**
 * Remove do `import { ... } from 'vue'` (single e multi-line)
 * os símbolos que já são auto-importados.
 */
function cleanVueImports(content) {
    // Captura tanto single-line quanto multi-line: import [type] { ... } from 'vue'
    const importRegex = /^import\s+(type\s+)?\{([^}]+)\}\s+from\s+['"]vue['"]\s*;?/gm;

    let changed = false;
    const modified = content.replace(importRegex, (match, typeKeyword, namedImports) => {
        const symbols = namedImports
            .split(',')
            .map(s => s.trim())
            .filter(Boolean);

        // Para cada símbolo, verifica se está na lista de auto-imports
        // Suporta aliases: "ref as vRef" → extrai "ref"
        const keep = symbols.filter(sym => {
            const name = sym.split(/\s+as\s+/)[0].trim();
            return !VUE_AUTO_IMPORTS.has(name);
        });

        if (keep.length === symbols.length) return match; // nada a remover

        changed = true;
        if (keep.length === 0) return ''; // remove a linha toda

        const isType = typeKeyword ? 'type ' : '';
        return `import ${isType}{ ${keep.join(', ')} } from 'vue'`;
    });

    return { content: modified, changed };
}

/**
 * Remove `import ComponentName from 'primevue/...'` em arquivos .vue.
 * Mantém serviços/plugins listados em PRIMEVUE_KEEP_PATHS.
 * Mantém named imports ({ useToast }) pois esses não são resolvidos pelo resolver de componentes.
 */
function cleanPrimeVueImports(content) {
    // Apenas default imports de componentes (PascalCase)
    const importRegex = /^import\s+([A-Z]\w*)\s+from\s+['"]primevue\/([^'"]+)['"]\s*;?\n?/gm;

    let changed = false;
    const modified = content.replace(importRegex, (match, componentName, path) => {
        const fullPath = `primevue/${path}`;
        if (PRIMEVUE_KEEP_PATHS.has(fullPath)) return match;

        changed = true;
        return '';
    });

    return { content: modified, changed };
}

/** Remove linhas em branco consecutivas excessivas (máx 2 \n seguidos) */
function collapseBlankLines(content) {
    return content.replace(/\n{3,}/g, '\n\n');
}

async function processFile(filePath) {
    const ext = extname(filePath);
    const original = await readFile(filePath, 'utf-8');

    let modified = original;
    let changed = false;

    // 1. Vue auto-imports → .vue e .js
    const vueResult = cleanVueImports(modified);
    if (vueResult.changed) {
        modified = vueResult.content;
        changed = true;
    }

    // 2. PrimeVue component imports → apenas .vue
    if (ext === '.vue') {
        const pvResult = cleanPrimeVueImports(modified);
        if (pvResult.changed) {
            modified = pvResult.content;
            changed = true;
        }
    }

    if (changed) {
        modified = collapseBlankLines(modified);
        if (!isDryRun) {
            await writeFile(filePath, modified, 'utf-8');
        }
    }

    return changed;
}

// ─── Main ─────────────────────────────────────────────────────────────────────

const __dirname = fileURLToPath(new URL('.', import.meta.url));
const srcDir = join(__dirname, '..', 'src');

console.log(isDryRun ? '🔍 Dry-run ativo — nenhum arquivo será alterado\n' : '');
console.log(`Varrendo: ${srcDir}\n`);

const files = await getAllFiles(srcDir);
console.log(`${files.length} arquivos encontrados...\n`);

let modifiedCount = 0;
let skippedCount = 0;

for (const file of files) {
    const wasModified = await processFile(file);
    if (wasModified) {
        console.log('✓', relative(srcDir, file));
        modifiedCount++;
    } else {
        skippedCount++;
    }
}

console.log(`\n─────────────────────────────────────────`);
console.log(`Modificados : ${modifiedCount} arquivos`);
console.log(`Sem mudança : ${skippedCount} arquivos`);
if (isDryRun) {
    console.log('\n⚠ Dry-run: rode sem --dry-run para aplicar as mudanças.');
}
