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

const { evaluatePromotion, runAutoPromotions } = await load('../services/promotionWorker.js');
const { createIntuneDeployment, loadDeploymentRaw } = await load('../models/psadtModel.js');

const owner = adminUserId();
const hoursAgo = (h) => new Date(Date.now() - h * 3_600_000).toISOString();

// --- pure eligibility -----------------------------------------------------

test('evaluatePromotion is due once the soak window elapses', () => {
  const d = { autoPromoteAfterHours: 1, autoPromoteRing: 'Broad', soakStartedAt: hoursAgo(2), promotedAt: '' };
  assert.equal(evaluatePromotion(d).due, true);
});

test('evaluatePromotion is not due while soaking, disabled, or already promoted', () => {
  assert.equal(evaluatePromotion({ autoPromoteAfterHours: 4, autoPromoteRing: 'Broad', soakStartedAt: hoursAgo(1), promotedAt: '' }).due, false);
  assert.equal(evaluatePromotion({ autoPromoteAfterHours: 0, autoPromoteRing: 'Broad', soakStartedAt: hoursAgo(5) }).due, false);
  assert.equal(evaluatePromotion({ autoPromoteAfterHours: 1, autoPromoteRing: 'Broad', soakStartedAt: hoursAgo(5), promotedAt: hoursAgo(1) }).due, false);
  assert.equal(evaluatePromotion({ autoPromoteAfterHours: 1, autoPromoteRing: '', soakStartedAt: hoursAgo(5) }).due, false);
});

// --- worker run -----------------------------------------------------------

test('runAutoPromotions promotes an eligible deployment and skips a soaking one', async () => {
  const eligible = createIntuneDeployment({
    name: 'Promote Me', visibility: 'shared', autoPromoteAfterHours: 1, autoPromoteRing: 'Broad', autoPromoteIntent: 'required',
    assignments: [{ ring: 'Broad', intent: 'available', groupId: 'g1', groupMode: 'group' }]
  }, owner);
  const soaking = createIntuneDeployment({
    name: 'Still Soaking', visibility: 'shared', autoPromoteAfterHours: 8, autoPromoteRing: 'Broad', autoPromoteIntent: 'required',
    assignments: [{ ring: 'Broad', intent: 'available', groupId: 'g2', groupMode: 'group' }]
  }, owner);

  // Start the soak clock: eligible elapsed, soaking just started.
  db.prepare('UPDATE intune_deployments SET soak_started_at = ? WHERE id = ?').run(hoursAgo(3), eligible.id);
  db.prepare('UPDATE intune_deployments SET soak_started_at = ? WHERE id = ?').run(hoursAgo(1), soaking.id);

  let pushed = 0;
  const summary = await runAutoPromotions({ pusher: async () => { pushed += 1; } });

  assert.ok(summary.promoted >= 1);
  const promoted = loadDeploymentRaw(eligible.id);
  assert.equal(promoted.assignments.find((a) => a.ring === 'Broad').intent, 'required');
  assert.ok(promoted.promotedAt);

  const stillSoaking = loadDeploymentRaw(soaking.id);
  assert.equal(stillSoaking.assignments.find((a) => a.ring === 'Broad').intent, 'available');
  assert.equal(stillSoaking.promotedAt, '');
  // Neither deployment has a Graph connection, so nothing was pushed.
  assert.equal(pushed, 0);
});
