import { mkdtempSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { readFileSync } from 'node:fs';
import { closeVendooDatabase, removeTempDirectory } from './test-runtime-cleanup.mjs';

const tempPrefix = process.env.VENDOO_TEST_TEMP_PREFIX || 'vendoo-invitations-';
const temp = mkdtempSync(join(tmpdir(), tempPrefix));
process.env.NODE_ENV = 'test';
process.env.VENDOO_DATA_DIR = temp;
process.env.VENDOO_DB_PATH = join(temp, 'db', 'vendoo.db');
process.env.VENDOO_CONFIG_PATH = join(temp, 'config', 'vendoo.env');

const failures = [];
const assert = (condition, message) => { if (!condition) failures.push(message); };
try {
  const identity = await import('../app/core/identity/identity-store.mjs');
  const { createUsersService } = await import('../app/modules/users/service.mjs');
  const first = identity.createAuthToken('tester@example.invalid', 'invite', 'viewer', null);
  assert(first.token && first.expiresAt, 'Einladungstoken oder Ablauf fehlt');
  let invitations = identity.listInvitations();
  assert(invitations.length === 1, `Erwartet eine Einladung, erhalten ${invitations.length}`);
  assert(invitations[0].status === 'pending', `Neue Einladung ist ${invitations[0].status}`);
  assert(!Object.hasOwn(invitations[0], 'token_hash'), 'Token-Hash wird in der Einladungsliste ausgegeben');
  assert(invitations[0].role === 'viewer', `Minimale Testerrolle ist ${invitations[0].role}`);

  const second = identity.createAuthToken('tester@example.invalid', 'invite', 'viewer', null);
  invitations = identity.listInvitations();
  assert(invitations.filter(item => item.status === 'pending').length === 1, 'Erneutes Senden lässt mehrere gültige Einladungen offen');
  const pending = invitations.find(item => item.status === 'pending');
  const revoked = identity.revokeInvitation(pending.id);
  assert(revoked?.status === 'revoked', 'Einladung wurde nicht widerrufen');
  assert(identity.validateAuthToken(second.token) === null, 'Widerrufener Link bleibt gültig');

  const service = createUsersService();
  const prepared = service.prepareInvite({ email: 'minimal@example.invalid', name: 'Minimal', createdBy: null, method: 'magic_link' });
  assert(prepared.role === 'viewer', `Service-Standardrolle ist ${prepared.role}`);

  const routes = readFileSync(new URL('../app/modules/users/routes.mjs', import.meta.url), 'utf8');
  for (const marker of ['/api/admin/users/invitations', '/api/admin/users/invitations/:id/resend', "'user.invitation_revoked'", "policy: 'users.manage'", 'csrf: true']) {
    assert(routes.includes(marker), `Einladungs-Routenvertrag fehlt: ${marker}`);
  }
  const frontend = readFileSync(new URL('../public/app.js', import.meta.url), 'utf8');
  assert(frontend.includes('loadAdminInvitations'), 'Einladungsübersicht fehlt im Frontend');
  assert(frontend.includes("invite-role').value = 'viewer'"), 'Einladungsdialog startet nicht mit Leserrolle');
} finally {
  await closeVendooDatabase({ failures, label: 'Einladungs-Testdatenbank' });
  await removeTempDirectory(temp, { failures, label: 'Einladungs-Testordner' });
}

if (failures.length) {
  console.error(`Controlled-Invitations-Gate 1.42.0 fehlgeschlagen (${failures.length}):`);
  failures.forEach(failure => console.error(`- ${failure}`));
  process.exit(1);
}
console.log('Controlled-Invitations-Gate 1.42.0 erfolgreich: Leser-Standardrolle, 48h-Ablauf, Einmalgültigkeit, erneutes Senden, Widerruf, Secret-Grenze, RBAC und UI geprüft.');
process.exit(0);
