// Unit tests for the manual control strategy.
// Run with: node --test test/basic/control-manual.basic.test.js

const test = require('node:test');
const assert = require('node:assert/strict');

const { UnitPolicy } = require('generalFunctions');
const manual = require('../../src/control/manual');

const unitPolicy = UnitPolicy.declare({
  canonical: { flow: 'm3/s' },
  output:    { flow: 'm3/s' },
  requireUnitForTypes: [],
});

function makeGroup(name) {
  const calls = { handleInput: [] };
  return {
    config: { general: { name } },
    handleInput: async (...args) => { calls.handleInput.push(args); },
    _calls: calls,
  };
}

function makeMachine(name) {
  const calls = { handleInput: [] };
  return {
    config: { general: { name } },
    handleInput: async (...args) => { calls.handleInput.push(args); },
    _calls: calls,
  };
}

function makeLogger() {
  return { info: () => {}, debug: () => {}, warn: () => {}, error: () => {} };
}

test('forwardDemand calls handleInput("parent", canonical m3/s demand) on every machine group', async () => {
  const groups = { a: makeGroup('A'), b: makeGroup('B'), c: makeGroup('C') };
  const ctx = { machineGroups: groups, machines: {}, unitPolicy, logger: makeLogger() };

  await manual.forwardDemand(ctx, 360);

  for (const g of Object.values(groups)) {
    assert.equal(g._calls.handleInput.length, 1);
    assert.deepEqual(g._calls.handleInput[0], ['parent', 0.1]);
  }
});

test('forwardDemand with no machineGroups but direct machines splits demand evenly', async () => {
  const machines = { m1: makeMachine('M1'), m2: makeMachine('M2'), m3: makeMachine('M3'), m4: makeMachine('M4') };
  const ctx = { machineGroups: {}, machines, logger: makeLogger() };

  await manual.forwardDemand(ctx, 80);

  for (const m of Object.values(machines)) {
    assert.equal(m._calls.handleInput.length, 1);
    assert.deepEqual(m._calls.handleInput[0], ['parent', 'execMovement', 20]);
  }
});

test('run() is a no-op (manual mode is event-driven)', async () => {
  const groups = { a: makeGroup('A') };
  const ctx = { machineGroups: groups, machines: {}, unitPolicy, logger: makeLogger() };
  await manual.run(ctx, { percControl: 0 });
  assert.equal(groups.a._calls.handleInput.length, 0);
});

test('manual exports name === "manual"', () => {
  assert.equal(manual.name, 'manual');
});
