import './setup.mjs';
import test from 'node:test';
import assert from 'node:assert/strict';
import { load } from './setup.mjs';

const { computeDrift } = await load('../services/intuneDriftService.js');
const { canPublish, canApprove } = await load('../services/graphRbac.js');

// --- drift ----------------------------------------------------------------

test('computeDrift reports in-sync when plan matches tenant', () => {
  const app = { displayName: 'Edge', publisher: 'Microsoft', installCommandLine: 'a', uninstallCommandLine: 'b', applicableArchitectures: 'x64' };
  const assignment = { intent: 'required', target: { '@odata.type': '#microsoft.graph.groupAssignmentTarget', groupId: 'g1' } };
  const rel = { '@odata.type': '#microsoft.graph.mobileAppSupersedence', targetId: 'old' };
  const drift = computeDrift({
    expectedApp: app, liveApp: { ...app },
    expectedAssignments: [assignment], liveAssignments: [assignment],
    expectedRelationships: [rel], liveRelationships: [rel]
  });
  assert.equal(drift.inSync, true);
});

test('computeDrift detects field, assignment, and relationship differences', () => {
  const drift = computeDrift({
    expectedApp: { displayName: 'Edge', installCommandLine: 'new' },
    liveApp: { displayName: 'Edge', installCommandLine: 'old' },
    expectedAssignments: [{ intent: 'required', target: { '@odata.type': '#microsoft.graph.groupAssignmentTarget', groupId: 'g1' } }],
    liveAssignments: [{ intent: 'available', target: { '@odata.type': '#microsoft.graph.groupAssignmentTarget', groupId: 'g1' } }],
    expectedRelationships: [{ '@odata.type': '#microsoft.graph.mobileAppSupersedence', targetId: 'old' }],
    liveRelationships: []
  });
  assert.equal(drift.inSync, false);
  assert.ok(drift.appDrift.some((d) => d.field === 'installCommandLine'));
  assert.equal(drift.assignmentDrift.missing.length, 1); // required|...|g1 missing in tenant
  assert.equal(drift.assignmentDrift.extra.length, 1);   // available|...|g1 extra in tenant
  assert.equal(drift.relationshipDrift.missing.length, 1);
});

// --- per-connection RBAC --------------------------------------------------

const admin = { id: 'u-admin', role: 'admin' };
const alice = { id: 'u-alice', role: 'user' };
const bob = { id: 'u-bob', role: 'user' };

test('canPublish: admins always; empty list allows all; otherwise listed only', () => {
  assert.equal(canPublish({ publisherIds: [] }, admin), true);
  assert.equal(canPublish({ publisherIds: [] }, alice), true);
  assert.equal(canPublish({ publisherIds: ['u-alice'] }, alice), true);
  assert.equal(canPublish({ publisherIds: ['u-alice'] }, bob), false);
});

test('canApprove: admins always; otherwise only named approvers (empty = none)', () => {
  assert.equal(canApprove({ approverIds: [] }, admin), true);
  assert.equal(canApprove({ approverIds: [] }, alice), false);
  assert.equal(canApprove({ approverIds: ['u-alice'] }, alice), true);
  assert.equal(canApprove({ approverIds: ['u-alice'] }, bob), false);
});

test('RBAC helpers tolerate JSON-string list columns', () => {
  assert.equal(canPublish({ publisher_ids: '["u-alice"]' }, alice), true);
  assert.equal(canApprove({ approver_ids: '["u-bob"]' }, bob), true);
});
