import { test } from 'node:test';
import assert from 'node:assert/strict';
import { Arbiter } from '../../src/core/Arbiter.js';

test('ADR-035/042: first-class core policy config sets conflict mode and reducers', () => {
  const arbiter = new Arbiter();
  const initial = arbiter.getPartialGraphPolicy();
  assert.equal(initial.conflict_mode, 'deterministic');

  arbiter.setPartialGraphPolicy({
    conflict_mode: 'strict',
    reducers: {
      request_has_timestamp: 'latest'
    }
  });

  const policy = arbiter.getPartialGraphPolicy();
  assert.equal(policy.conflict_mode, 'strict');
  assert.equal(policy.reducers.request_has_timestamp, 'latest');

  const snapshot = arbiter.getPartialGraphPolicySnapshot();
  assert.equal(snapshot.conflict_mode, 'strict');
  assert.equal(snapshot.reducer_count, 1);
});

test('ADR-035/042: DSL relation config can declare partial-graph reducer policy', () => {
  const arbiter = new Arbiter();
  arbiter.setRelationConfig('request_has_timestamp', {
    type: 'direct',
    partial_graph: {
      reducer: 'latest'
    }
  });

  const policy = arbiter.getPartialGraphPolicy();
  assert.equal(policy.reducers.request_has_timestamp, 'latest');
});

test('ADR-035/042: policy-level strict conflict mode is enforced by default', () => {
  const arbiter = new Arbiter({
    partialGraphPolicy: {
      conflict_mode: 'strict'
    }
  });
  arbiter.addNode('user:1', 'user');
  arbiter.addNode('obj:1', 'obj');
  arbiter.setRelationConfig('request_has_id', { type: 'direct' });

  assert.throws(() => {
    arbiter._createPartialGraphContext({
      relations: [
        {
          src: 'user:1',
          relation: 'request_has_id',
          dst: 'obj:1',
          value: 1,
          layer_name: 'request_observed'
        },
        {
          src: 'user:1',
          relation: 'request_has_id',
          dst: 'obj:1',
          value: 2,
          layer_name: 'request_observed'
        }
      ]
    });
  }, /partial_graph_conflict_without_reducer/);
});

test('ADR-035/042: request options can override core policy conflict mode', () => {
  const arbiter = new Arbiter({
    partialGraphPolicy: {
      conflict_mode: 'strict'
    }
  });
  arbiter.addNode('user:1', 'user');
  arbiter.addNode('obj:1', 'obj');
  arbiter.setRelationConfig('request_has_id', { type: 'direct' });

  const context = arbiter._createPartialGraphContext({
    options: {
      conflict_mode: 'deterministic'
    },
    relations: [
      {
        src: 'user:1',
        relation: 'request_has_id',
        dst: 'obj:1',
        value: 1,
        layer_name: 'request_observed'
      },
      {
        src: 'user:1',
        relation: 'request_has_id',
        dst: 'obj:1',
        value: 2,
        layer_name: 'request_observed'
      }
    ]
  });

  const srcId = arbiter.nodeIdByKey.get('user:1');
  const dstId = arbiter.nodeIdByKey.get('obj:1');
  const rel = context.getDirectRelation(srcId, 'request_has_id', dstId);
  assert.ok(rel);
});
