import { test } from 'node:test';
import assert from 'node:assert/strict';
import { reduceConflictingFacts, listSupportedReducers } from '../../../src/core/partial-graph/reducers.js';

function fact(overrides = {}) {
  return {
    src: 1,
    rel: 'request_has_timestamp',
    dst: 2,
    possibility: 0.7,
    reliability: 0.9,
    value: 10,
    attributes: null,
    updated_last_at: 100,
    changed_last_at: 100,
    layer_name: 'request_observed',
    source: 'partial',
    ...overrides
  };
}

test('ADR-042 reducer set is explicitly supported', () => {
  assert.deepEqual(listSupportedReducers().sort(), [
    'dedupe',
    'first',
    'ignore_conflict',
    'latest',
    'max_value',
    'min_value',
    'strongest',
    'union_refs',
    'unique',
    'weakest'
  ]);
});

test('ADR-042 trust filtering applies before reducer selection', () => {
  const highTrust = fact({ possibility: 0.2, layer_name: 'token_projection' });
  const lowTrust = fact({ possibility: 0.9, layer_name: 'caller_declared' });
  const reduced = reduceConflictingFacts([lowTrust, highTrust], 'strongest');
  assert.equal(reduced.fact.possibility, 0.2);
});

test('ADR-042 ignore_conflict returns absent on incompatible same-trust facts', () => {
  const a = fact({ value: 10 });
  const b = fact({ value: 20 });
  const reduced = reduceConflictingFacts([a, b], 'ignore_conflict');
  assert.equal(reduced.fact, null);
  assert.equal(reduced.audit.reason_code, 'ignore_conflict_absent');
});

test('ADR-042 latest reducer picks freshest same-trust fact', () => {
  const older = fact({ value: 10, updated_last_at: 100 });
  const newer = fact({ value: 20, updated_last_at: 200 });
  const reduced = reduceConflictingFacts([older, newer], 'latest');
  assert.equal(reduced.fact.value, 20);
});

test('ADR-042 min/max reducers select bounded numeric values', () => {
  const a = fact({ value: 10 });
  const b = fact({ value: 20 });
  const minReduced = reduceConflictingFacts([a, b], 'min_value');
  const maxReduced = reduceConflictingFacts([a, b], 'max_value');
  assert.equal(minReduced.fact.value, 10);
  assert.equal(maxReduced.fact.value, 20);
});

test('ADR-042 strongest/weakest are deterministic after trust filtering', () => {
  const weaker = fact({ possibility: 0.3, reliability: 0.8 });
  const stronger = fact({ possibility: 0.9, reliability: 1.0 });
  const strongest = reduceConflictingFacts([weaker, stronger], 'strongest');
  const weakest = reduceConflictingFacts([weaker, stronger], 'weakest');
  assert.equal(strongest.fact.possibility, 0.9);
  assert.equal(weakest.fact.possibility, 0.3);
});

test('ADR-042 union_refs merges reference sets without authority values', () => {
  const a = fact({ rel: 'provenance_hash_ref', value: null, attributes: { refs: ['hash:a'] } });
  const b = fact({ rel: 'provenance_hash_ref', value: null, attributes: { refs: ['hash:b', 'hash:a'] } });
  const reduced = reduceConflictingFacts([a, b], 'union_refs');
  assert.deepEqual(reduced.fact.attributes.refs, ['hash:a', 'hash:b']);
});
