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

const ValidationUtils = require('../src/helper/validationUtils.js');

const schema = {
  functionality: {
    softwareType: {
      default: 'measurement',
      rules: { type: 'string' },
    },
  },
  enabled: {
    default: true,
    rules: { type: 'boolean' },
  },
  mode: {
    default: 'auto',
    rules: {
      type: 'enum',
      values: [{ value: 'auto' }, { value: 'manual' }],
    },
  },
  name: {
    default: 'sensor',
    rules: { type: 'string' },
  },
  asset: {
    default: {},
    rules: {
      type: 'object',
      schema: {
        unit: {
          default: 'm3/h',
          rules: { type: 'string' },
        },
        curveUnits: {
          default: {},
          rules: {
            type: 'object',
            schema: {
              power: {
                default: 'kW',
                rules: { type: 'string' },
              },
            },
          },
        },
      },
    },
  },
};

test('validateSchema applies defaults and type coercion where supported', () => {
  const validation = new ValidationUtils(false, 'error');
  const result = validation.validateSchema({ enabled: 'true', name: 'SENSOR' }, schema, 'test');

  assert.equal(result.enabled, true);
  assert.equal(result.name, 'SENSOR');
  assert.equal(result.mode, 'auto');
  assert.equal(result.functionality.softwareType, 'measurement');
});

test('enum with non-string value falls back to default', () => {
  const validation = new ValidationUtils(false, 'error');
  const result = validation.validateSchema({ mode: 123 }, schema, 'test');
  assert.equal(result.mode, 'auto');
});

test('curve validation falls back to default for invalid dimension structure', () => {
  const validation = new ValidationUtils(false, 'error');
  const defaultCurve = { 1: { x: [1, 2], y: [10, 20] } };
  const invalid = { 1: { x: [2, 1], y: [20, 10] } };
  const curve = validation.validateCurve(invalid, defaultCurve);
  assert.deepEqual(curve, defaultCurve);
});

test('removeUnwantedKeys handles primitive values without throwing', () => {
  const validation = new ValidationUtils(false, 'error');
  const input = {
    a: { default: 1, rules: { type: 'number' } },
    b: 2,
    c: 'x',
  };
  assert.doesNotThrow(() => validation.removeUnwantedKeys(input));
});

test('unit-like fields preserve case while regular strings are normalized', () => {
  const validation = new ValidationUtils(false, 'error');
  const result = validation.validateSchema(
    {
      name: 'RotatingMachine',
      asset: {
        unit: 'kW',
        curveUnits: { power: 'kW' },
      },
    },
    schema,
    'machine'
  );

  assert.equal(result.name, 'RotatingMachine');
  assert.equal(result.asset.unit, 'kW');
  assert.equal(result.asset.curveUnits.power, 'kW');
});

test('array with minLength 0 accepts empty arrays without fallback warning path', () => {
  const validation = new ValidationUtils(false, 'error');
  const localSchema = {
    functionality: {
      softwareType: {
        default: 'measurement',
        rules: { type: 'string' },
      },
    },
    assetRegistration: {
      default: { childAssets: ['default'] },
      rules: {
        type: 'object',
        schema: {
          childAssets: {
            default: ['default'],
            rules: {
              type: 'array',
              itemType: 'string',
              minLength: 0,
            },
          },
        },
      },
    },
  };

  const result = validation.validateSchema(
    { assetRegistration: { childAssets: [] } },
    localSchema,
    'measurement'
  );

  assert.deepEqual(result.assetRegistration.childAssets, []);
});
