// Throwaway probe — exercises the exact path:
//   measurement child writes flow.measured.upstream → pumpingStation parent
//   subscribes → getOutput() (≡ what Port 0 emits).
// Run with: node --test test/basic/_probe_upstream_emit.test.js

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

const PumpingStation = require('../../src/specificClass');
const { MeasurementContainer, configManager } = require('generalFunctions');
const EventEmitter = require('node:events');

// Minimal PumpingStation config — matches the editor defaults shape.
function makePsConfig() {
  const ui = {
    name: 'PS', basinVolume: 50, basinHeight: 5,
    inflowLevel: 3, outflowLevel: 0.2, overflowLevel: 4.5,
    minHeightBasedOn: 'outlet',
    controlMode: 'levelbased',
    minLevel: 1, startLevel: 2, maxLevel: 4,
    levelCurveType: 'linear',
    processOutputFormat: 'process', dbaseOutputFormat: 'influxdb',
  };
  const cm = new configManager();
  // Use the same buildConfig pipeline the runtime uses.
  return cm.buildConfig('pumpingStation', ui, 'ps-probe', {
    basin: {
      volume: 50, height: 5, inflowLevel: 3, outflowLevel: 0.2, overflowLevel: 4.5,
    },
    hydraulics: { minHeightBasedOn: 'outlet' },
    control: {
      mode: 'levelbased',
      allowedModes: new Set(['levelbased']),
      levelbased: { minLevel: 1, startLevel: 2, maxLevel: 4, curveType: 'linear' },
    },
    safety: {},
  });
}

// Fake measurement child that looks exactly like the real one to the router:
//   - softwareType 'measurement'
//   - config.asset.type = 'flow'
//   - config.functionality.positionVsParent = 'upstream'
//   - .measurements is a real MeasurementContainer with a real emitter
function makeMeasurementChild(id = 'meas-probe') {
  const measurements = new MeasurementContainer({
    autoConvert: true,
    preferredUnits: { flow: 'm3/s' },
  });
  // Real container ships an emitter; sanity check.
  assert.ok(measurements.emitter instanceof EventEmitter || typeof measurements.emitter?.on === 'function');
  return {
    id,
    source: {
      config: {
        general: { id, name: id },
        functionality: { softwareType: 'measurement', positionVsParent: 'upstream' },
        asset: { type: 'flow' },
      },
      measurements,
    },
  };
}

test('PROBE: measurement child writes flow.measured.upstream — parent surfaces it on getOutput()', () => {
  const ps = new PumpingStation(makePsConfig());
  const child = makeMeasurementChild();

  // Register the child the same way the runtime does.
  ps.childRegistrationUtils.registerChild(child.source, 'upstream');

  // Drive a value through the child's MeasurementContainer the way Channel
  // does — type/variant/position chain then .value().
  child.source.measurements
    .type('flow').variant('measured').position('upstream')
    .value(12, Date.now(), 'm3/h');   // 12 m³/h ≈ 0.00333 m³/s

  const out = ps.getOutput();
  const upstreamKeys = Object.keys(out).filter((k) => k.startsWith('flow.measured.upstream'));
  console.log('flow.measured.upstream.* keys in Port 0 payload:', upstreamKeys);
  for (const k of upstreamKeys) console.log(`  ${k} = ${out[k]}`);

  // The contract: the parent should surface the upstream measurement.
  assert.ok(upstreamKeys.length > 0, 'parent must surface flow.measured.upstream.* on Port 0');
});
