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

const ConfigManager = require('../src/configs/index.js');

test('buildConfig deep-merges domainConfig so general.id and asset.model survive', () => {
  // Regression: previously this used Object.assign (shallow), so a
  // buildDomainConfig that returned {general:{unit:'m3/h'}, asset:{curveUnits:...}}
  // wiped general.id (→ null via schema default) and asset.model (→ "Unknown"),
  // which collapsed MGC child registration (id collision) and broke curve loading.
  const manager = new ConfigManager('.');
  const uiConfig = {
    name: 'PumpA',
    model: 'hidrostal-H05K-S03R',
    supplier: 'Hidrostal',
    category: 'pump',
    assetType: 'Centrifugal',
    unit: 'm3/h',
  };
  const domainConfig = {
    general: { unit: 'm3/h' },
    asset:   { curveUnits: { pressure: 'mbar', flow: 'm3/h', power: 'kW', control: '%' } },
  };
  const cfg = manager.buildConfig('rotatingMachine', uiConfig, 'node-abc-123', domainConfig);

  assert.equal(cfg.general.id,   'node-abc-123', 'general.id must come from nodeId');
  assert.equal(cfg.general.name, 'PumpA',         'general.name must come from uiConfig.name');
  assert.equal(cfg.general.unit, 'm3/h',          'general.unit must come from domainConfig');
  assert.equal(cfg.asset.model,    'hidrostal-H05K-S03R', 'asset.model must come from uiConfig.model');
  assert.equal(cfg.asset.supplier, 'Hidrostal',           'asset.supplier must survive merge');
  assert.deepEqual(cfg.asset.curveUnits, domainConfig.asset.curveUnits,
    'asset.curveUnits must come from domainConfig');
});

test('buildConfig: two nodes with same uiConfig keep distinct general.id', () => {
  // Regression: MGC.onRegister('machine') keys by config.general.id; if two
  // machines collapse to the same id (e.g. null), the second is rejected.
  const manager = new ConfigManager('.');
  const ui = { model: 'hidrostal-H05K-S03R', supplier: 'Hidrostal', unit: 'm3/h' };
  const dom = { general: { unit: 'm3/h' }, asset: { curveUnits: { pressure: 'mbar' } } };
  const a = manager.buildConfig('rotatingMachine', ui, 'red-node-A', dom);
  const b = manager.buildConfig('rotatingMachine', ui, 'red-node-B', dom);
  assert.notEqual(a.general.id, b.general.id);
  assert.equal(a.general.id, 'red-node-A');
  assert.equal(b.general.id, 'red-node-B');
});

test('can read known config and report existence', () => {
  const manager = new ConfigManager('.');
  assert.equal(manager.hasConfig('measurement'), true);

  const config = manager.getConfig('measurement');
  assert.ok(config.functionality);
  assert.ok(config.functionality.softwareType);
});

test('getAvailableConfigs includes known names', () => {
  const manager = new ConfigManager('.');
  const configs = manager.getAvailableConfigs();
  assert.ok(configs.includes('measurement'));
  assert.ok(configs.includes('rotatingMachine'));
});

test('createEndpoint creates executable JS payload shell', () => {
  const manager = new ConfigManager('.');
  const script = manager.createEndpoint('measurement');

  assert.match(script, /window\.EVOLV\.nodes\.measurement/);
  assert.match(script, /config loaded and endpoint created/);
});

test('getConfig throws on missing config', () => {
  const manager = new ConfigManager('.');
  assert.throws(() => manager.getConfig('definitely-not-real'), /Failed to load config/);
});
