import { readFileSync, existsSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';

const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const pkg = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8'));
const failures = [];
const importPattern = /(?:import\s+(?:[^'";]+?\s+from\s+)?|import\s*\()\s*['"]([^'"]+)['"]/g;

function resolveImport(fromFile, specifier) {
  if (!specifier.startsWith('.')) return null;
  const base = resolve(dirname(fromFile), specifier);
  const candidates = [base, `${base}.mjs`, `${base}.js`, resolve(base, 'index.mjs'), resolve(base, 'index.js')];
  return candidates.find((candidate) => existsSync(candidate)) || null;
}

const dependencyCache = new Map();
function dependencyClosure(file, visiting = new Set()) {
  if (dependencyCache.has(file)) return dependencyCache.get(file);
  if (visiting.has(file)) return new Set();
  visiting.add(file);
  const source = readFileSync(file, 'utf8');
  const result = new Set();
  for (const match of source.matchAll(importPattern)) {
    const dependency = resolveImport(file, match[1]);
    if (!dependency) continue;
    result.add(dependency);
    for (const nested of dependencyClosure(dependency, new Set(visiting))) result.add(nested);
  }
  dependencyCache.set(file, result);
  return result;
}

function collectVerifierFiles(scriptName, seen = new Set()) {
  if (seen.has(scriptName)) return [];
  seen.add(scriptName);
  const command = pkg.scripts?.[scriptName] || '';
  const files = [];
  for (const match of command.matchAll(/npm run ([\w:-]+)/g)) files.push(...collectVerifierFiles(match[1], new Set(seen)));
  for (const match of command.matchAll(/node(?: --no-warnings)? (tools\/[A-Za-z0-9._-]+\.mjs)/g)) files.push(resolve(root, match[1]));
  return files;
}

const dbModule = resolve(root, 'lib/db.mjs');
const activeFiles = [...new Set(collectVerifierFiles('verify:all'))];
for (const file of activeFiles) {
  const source = readFileSync(file, 'utf8');
  const dependencies = dependencyClosure(file);
  const opensVendooDatabase = dependencies.has(dbModule);
  if (!opensVendooDatabase) continue;
  if (!source.includes('VENDOO_DATA_DIR') || !source.includes('VENDOO_DB_PATH')) failures.push(`${file.slice(root.length + 1)} öffnet lib/db.mjs transitiv ohne isolierten Test-Datenpfad.`);
  if (!source.includes('closeVendooDatabase')) failures.push(`${file.slice(root.length + 1)} öffnet lib/db.mjs transitiv, schließt die Datenbank aber nicht explizit.`);
  if (!source.includes('removeTempDirectory')) failures.push(`${file.slice(root.length + 1)} verwendet nicht den Windows-tauglichen Temp-Cleanup.`);
}

for (const required of [
  'tools/test-runtime-cleanup.mjs',
  'tools/verify-controlled-invitations-1.42.0.mjs',
  'tools/verify-initial-disabled-modules-1.41.2.mjs',
  'tools/verify-windows-sqlite-cleanup-regression-1.43.0.mjs',
]) {
  if (!existsSync(resolve(root, required))) failures.push(`Pflichtdatei fehlt: ${required}`);
}

if (failures.length) {
  console.error(`SQLite-Cleanup-Vertragsprüfung 1.43.0 fehlgeschlagen (${failures.length}):`);
  for (const failure of failures) console.error(`- ${failure}`);
  process.exit(1);
}
console.log(`SQLite-Cleanup-Vertragsprüfung 1.43.0 erfolgreich: ${activeFiles.length} aktive Verifier transitiv geprüft; alle Vendoo-DB-Temp-Tests schließen ihre Handles.`);
