async function run() {
  // No-op: manual mode is event-driven via set.demand → forwardDemand,
  // not tick-driven.
}

async function forwardDemand(ctx, demand) {
  const { machineGroups, machines, unitPolicy, logger } = ctx;
  logger?.info?.(`Manual demand forwarded: ${demand}`);

  if (machineGroups && Object.keys(machineGroups).length > 0) {
    const groupDemand = unitPolicy.convert(demand, 'm3/h', 'm3/s', 'manual demand to machineGroups');
    await Promise.all(
      Object.values(machineGroups).map((group) =>
        group.handleInput('parent', groupDemand).catch((err) => {
          logger?.error?.(`Failed to forward demand to group: ${err.message}`);
        })
      )
    );
  }

  if (machines && Object.keys(machines).length > 0) {
    const perMachine = demand / Object.keys(machines).length;
    for (const machine of Object.values(machines)) {
      try {
        await machine.handleInput('parent', 'execMovement', perMachine);
      } catch (err) {
        logger?.error?.(`Failed to forward demand to machine: ${err.message}`);
      }
    }
  }

  // Neither a group nor a direct machine is registered, so the operator's
  // demand silently goes nowhere. Surface it — the usual cause is a dropped
  // Port 2 parent↔child registration after a partial redeploy.
  const noGroups = !machineGroups || Object.keys(machineGroups).length === 0;
  const noMachines = !machines || Object.keys(machines).length === 0;
  if (noGroups && noMachines) {
    logger?.warn?.(
      `Manual demand ${demand} not forwarded — no machine group or machine is registered to this pumping station. `
      + `Check the parent↔child Port 2 registration (redeploy/restart fully to restore it).`
    );
  }
}

module.exports = {
  name: 'manual',
  run,
  forwardDemand,
};
