'use strict';

const fs = require('fs');
const path = require('path');

const root = __dirname;
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
const checks = [];
const expect = (condition, message) => checks.push({ ok: Boolean(condition), message });

const login = read('login.php');
const callback = read('auth_entra_callback.php');
const entra = read(path.join('app', 'entra.php'));
const auth = read(path.join('app', 'auth.php'));
const migration = read('upgrade_entra_auth.sql');
const rollback = read('rollback_entra_auth.sql');
const composer = JSON.parse(read('composer.json'));

expect(login.includes("password_verify("), 'Lokalni password login je zadržan.');
expect(login.includes("establish_authenticated_session") && callback.includes("establish_authenticated_session"), 'Oba login toka koriste isti session helper.');
expect(auth.includes("session_regenerate_id(true)"), 'Uspešna prijava regeneriše session ID.');
expect(auth.includes("$_SESSION['user_id']"), 'Postojeći user_id session model je zadržan.');
expect(login.includes('auth/entra/login'), 'Login UI sadrži Microsoft opciju.');
expect(entra.includes("setCodeChallengeMethod('S256')"), 'PKCE S256 je uključen.');
expect(entra.includes('setAllowImplicitFlow(false)'), 'Implicit flow je isključen.');
expect(entra.includes('entra_validate_callback_state()'), 'State ima eksplicitnu validaciju i rok.');
expect(entra.includes("$claims->nonce") && entra.includes('hash_equals($expectedNonce'), 'Nonce je obavezan i poredi se konstantnim vremenom.');
expect(entra.includes("$header->alg") && entra.includes("'RS256'"), 'ID token mora koristiti RS256.');
expect(entra.includes("$claims->tid") && entra.includes("$claims->oid"), 'Tenant ID i Entra Object ID se proveravaju.');
expect(entra.includes('FROM users WHERE entra_object_id = ?'), 'Ponovljeni login traži korisnika po trajnom Object ID-u.');
expect(entra.includes('WHERE email IN') && entra.includes('AND entra_object_id IS NULL'), 'Prvi login radi ograničeno account linking povezivanje.');
expect(!entra.includes('INSERT INTO users'), 'Microsoft login ne kreira ticketing korisnike.');
expect(!entra.match(/Directory\.Read|User\.Read|Group\.Read|Graph/i), 'Nema Microsoft Graph/directory privilegija.');
expect(migration.includes('entra_object_id') && migration.includes('UNIQUE KEY'), 'Migracija dodaje jedinstveni Object ID.');
expect(rollback.includes('DROP COLUMN `entra_object_id`') && !rollback.includes('password_hash'), 'Rollback uklanja samo Entra podatke.');
expect(composer.require['jumbojett/openid-connect-php'] === '1.0.2', 'OIDC biblioteka je fiksirana na proverenu verziju.');
expect(callback.includes('AUTH_ENTRA_SUCCESS') && callback.includes('AUTH_ENTRA_ACCOUNT_LINKED'), 'Entra uspeh i linking imaju audit događaje.');
expect(login.includes('AUTH_LOCAL_SUCCESS') && login.includes('AUTH_LOCAL_FAILED'), 'Lokalni login ima standardizovane audit događaje.');

const unsafeLogging = [entra, callback].some((source) => /(?:error_log|security_log_event|auth_audit_event)\s*\([^\n]*(?:id_token|access_token|refresh_token|client_secret|authorization_code)/i.test(source));
expect(!unsafeLogging, 'Tokeni, kod i secret se ne prosleđuju log funkcijama.');

for (const check of checks) {
    console.log(`${check.ok ? 'PASS' : 'FAIL'}: ${check.message}`);
}

const failed = checks.filter((check) => !check.ok);
if (failed.length > 0) {
    process.exitCode = 1;
} else {
    console.log(`PASS: ${checks.length} Entra auth statičkih/regresionih provera.`);
}
