import { mkdtempSync, readFileSync, rmSync, writeFileSync, mkdirSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { ModuleRegistry } from '../app/kernel/module-registry.mjs';
import { ModuleStateStore } from '../app/core/modules/module-state-store.mjs';
import { ModulePackageStore } from '../app/core/modules/module-package-store.mjs';
import { buildModulePackage } from '../app/core/modules/module-package-contract.mjs';
import { ModuleManagerService } from '../app/modules/module-manager/service.mjs';

const failures = [];
const assert = (condition, message) => { if (!condition) failures.push(message); };
const expectThrow = async (fn, code, message) => {
  try { await fn(); failures.push(message); }
  catch (error) { if (code && error.code !== code) failures.push(`${message} (${error.code || error.message})`); }
};

function manifest(id, { requires = [], type = 'feature', status = 'native', owns = [], provides = [], consumes = [] } = {}) {
  return { schemaVersion: 1, id, name: id, version: '1.0.0', type, status, description: id, requires, permissions: [], provides, consumes, owns };
}

const temp = mkdtempSync(join(tmpdir(), 'vendoo-modules-140-'));
try {
  const stateStore = new ModuleStateStore(join(temp, 'config', 'modules-state.json'));
  const packageStore = new ModulePackageStore(join(temp, 'modules'));
  const registry = new ModuleRegistry();
  registry.register({ manifest: manifest('vendoo.security', { type: 'core', provides: ['security.policies'], owns: ['security.state'] }), lifecycle: { async health(){return {ok:true}} } });
  registry.register({ manifest: manifest('vendoo.settings', { type: 'core', requires: ['vendoo.security'], provides: ['settings.configuration'], consumes: ['security.policies'], owns: ['settings.state'] }), lifecycle: { async health(){return {ok:true}} } });
  registry.register({ manifest: manifest('vendoo.ai', { requires: ['vendoo.security'], provides: ['ai.images'], consumes: ['security.policies'], owns: ['ai.jobs'] }), lifecycle: { async health(){return {ok:true}} } });
  registry.register({ manifest: manifest('vendoo.flux-studio', { requires: ['vendoo.ai'], consumes: ['ai.images'], owns: ['flux.jobs'] }), lifecycle: { async health(){return {ok:true}} } });
  const context = { modules: registry, moduleStateStore: stateStore, modulePackageStore: packageStore };
  await registry.startAll(context);
  const service = new ModuleManagerService({ modules: registry, stateStore, packageStore, context });

  await expectThrow(() => service.disable('vendoo.security'), 'MODULE_PROTECTED', 'Geschütztes Kernmodul konnte deaktiviert werden');
  await service.disable('vendoo.ai', { cascade: true });
  assert(!registry.isEnabled('vendoo.ai') && !registry.isEnabled('vendoo.flux-studio'), 'Abhängige optionale Module wurden nicht gemeinsam deaktiviert');
  await service.enable('vendoo.flux-studio');
  assert(registry.isEnabled('vendoo.ai') && registry.isEnabled('vendoo.flux-studio'), 'Abhängigkeiten wurden beim Aktivieren nicht automatisch gestartet');
  assert(stateStore.isEnabled('vendoo.ai') && stateStore.isEnabled('vendoo.flux-studio'), 'Aktivierungsstatus wurde nicht persistiert');

  const externalManifest = manifest('vendoo.ext-demo', { type: 'extension-host', owns: ['ext-demo.state'], provides: ['ext-demo.metadata'] });
  const packageData = buildModulePackage({
    manifest: externalManifest,
    runtime: { mode: 'declarative', entry: null },
    files: [{ path: 'README.md', content: '# Demo\n' }, { path: 'module-ui.json', content: '{"label":"Demo"}\n' }],
  });
  const installed = service.install(Buffer.from(JSON.stringify(packageData), 'utf8'));
  assert(installed.id === 'vendoo.ext-demo' && installed.source === 'external', 'Deklaratives Fremdmodul wurde nicht installiert');
  await service.enable('vendoo.ext-demo');
  assert(registry.isEnabled('vendoo.ext-demo'), 'Deklaratives Fremdmodul wurde nicht aktiviert');
  const exported = service.export('vendoo.ext-demo');
  assert(exported.length > 100 && JSON.parse(exported.toString('utf8')).manifest.id === 'vendoo.ext-demo', 'Fremdmodul-Export ist ungültig');
  await service.disable('vendoo.ext-demo');
  await service.remove('vendoo.ext-demo');
  assert(!registry.has('vendoo.ext-demo') && !packageStore.get('vendoo.ext-demo'), 'Fremdmodul wurde nicht vollständig entfernt');

  const executableDraft = {
    manifest: manifest('vendoo.ext-unsafe', { type: 'extension-host', owns: ['ext-unsafe.state'] }),
    runtime: { mode: 'declarative', entry: null },
    files: [{ path: 'index.mjs', content: 'export default 1;' }],
  };
  await expectThrow(() => Promise.resolve(buildModulePackage(executableDraft)), 'MODULE_PACKAGE_EXECUTABLE_FORBIDDEN', 'Ausführbarer Code wurde in deklarativem Paket akzeptiert');

  const isolated = buildModulePackage({
    manifest: manifest('vendoo.ext-isolated', { type: 'extension-host', owns: ['ext-isolated.state'] }),
    runtime: { mode: 'isolated', entry: 'index.mjs' },
    files: [{ path: 'index.mjs', content: 'export default {};' }],
  });
  const isolatedInstalled = service.install(Buffer.from(JSON.stringify(isolated), 'utf8'));
  assert(isolatedInstalled.package?.activatable === false, 'Unsigniertes ausführbares Modul ist aktivierbar');
  await expectThrow(() => service.enable('vendoo.ext-isolated'), 'MODULE_NOT_ACTIVATABLE', 'Unsigniertes ausführbares Modul wurde aktiviert');

  const stateFile = JSON.parse(readFileSync(join(temp, 'config', 'modules-state.json'), 'utf8'));
  assert(stateFile.schemaVersion === 1 && stateFile.modules['vendoo.ai'], 'Persistente Modulstatusdatei ist unvollständig');
  assert(service.catalog().summary.total >= 5, 'Modulkatalog ist unvollständig');
} finally {
  rmSync(temp, { recursive: true, force: true });
}

if (failures.length) {
  console.error(`Module-Manager-Gate 1.41.1 fehlgeschlagen (${failures.length}):`);
  failures.forEach(item => console.error(`- ${item}`));
  process.exit(1);
}
console.log('Module-Manager-Gate 1.41.1 erfolgreich: Kernschutz, Abhängigkeitskaskade, Persistenz, .vmod-Import/Export, Entfernung und Quarantäne geprüft.');
