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

describe('Cache invalidation paths', () => {
  test('relation lookup cache clears on removal', () => {
    const arbiter = new Arbiter();
    arbiter.addNode('user', 'user');
    arbiter.addNode('doc', 'document');
    arbiter.addRelation('user', 'can_read', 'doc', 1.0);

    const srcId = arbiter.nodeIdByKey.get('user');
    const dstId = arbiter.nodeIdByKey.get('doc');
    const cacheKey = arbiter.relationManager._makeDirectCacheKey(srcId, 'can_read', dstId);

    const relation = arbiter.relationManager.getDirectRelation(srcId, 'can_read', dstId);
    assert.ok(relation);
    // RF-08: cache state moved entirely to RelationCaches.
    assert.ok(arbiter.relationManager._caches.relationLookupCache.has(cacheKey));

    arbiter.removeRelation('user', 'can_read', 'doc');
    assert.ok(!arbiter.relationManager._caches.relationLookupCache.has(cacheKey));
  });

  test('value cache clears on relation modification', () => {
    const arbiter = new Arbiter();
    arbiter.addNode('user', 'user');
    arbiter.addNode('account', 'account');
    arbiter.addRelation('user', 'has_balance', 'account', 1.0, { value: 10 });

    const srcId = arbiter.nodeIdByKey.get('user');
    const dstId = arbiter.nodeIdByKey.get('account');
    const cacheKey = arbiter.relationManager._makeValueCacheKey(srcId, 'has_balance', dstId);

    const valueRelation = arbiter.relationManager.getValueRelation(srcId, 'has_balance', dstId);
    assert.ok(valueRelation);
    assert.ok(arbiter.relationManager._caches.valueLookupCache.has(cacheKey));

    arbiter.relationManager._modifyRelation('user', 'has_balance', 'account', { value: 20 });
    assert.ok(!arbiter.relationManager._caches.valueLookupCache.has(cacheKey));
  });

  test('direct check cache clears on relation removal', () => {
    const arbiter = new Arbiter();
    arbiter.addNode('user', 'user');
    arbiter.addNode('doc', 'document');
    arbiter.addRelation('user', 'can_read', 'doc', 1.0);
    arbiter.setRelationConfig('can_read', { type: 'direct' });

    const result = arbiter.check('user', 'can_read', 'doc');
    assert.strictEqual(result.possibility, 1.0);

    const srcId = arbiter.keyManager.getStringId('user');
    const dstId = arbiter.keyManager.getStringId('doc');
    const cacheKey = arbiter.keyManager.createCompositeKey(srcId, 'can_read', dstId);
    assert.ok(arbiter.directCheckCache.has(cacheKey));

    arbiter.removeRelation('user', 'can_read', 'doc');
    assert.ok(!arbiter.directCheckCache.has(cacheKey));
  });

  test('value cache invalidation schedules stale recompute', () => {
    const arbiter = new Arbiter();
    arbiter.addNode('user', 'user');
    arbiter.addNode('account', 'account');
    arbiter.addRelation('user', 'has_balance', 'account', 1.0, { value: 10 });

    const srcId = arbiter.nodeIdByKey.get('user');
    const dstId = arbiter.nodeIdByKey.get('account');
    const valueRelation = arbiter.relationManager.getValueRelation(srcId, 'has_balance', dstId);
    assert.ok(valueRelation);

    arbiter.relationManager._modifyRelation('user', 'has_balance', 'account', { value: 20 });
    assert.strictEqual(arbiter.valueManager.staleValueItemsIndex.size, 0);
  });
});
