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

describe('Graph Structure and Queries', () => {
  test('basic node and relation creation', () => {
    const arbiter = new Arbiter();
    
    arbiter.addNode('user:1', 'user');
    arbiter.addNode('resource:1', 'resource');
    
    const nodeId1 = arbiter.resolveNodeId('user:1');
    const nodeId2 = arbiter.resolveNodeId('resource:1');
    
    assert.ok(nodeId1 !== undefined, 'user node ID resolved');
    assert.ok(nodeId2 !== undefined, 'resource node ID resolved');
    assert.strictEqual(arbiter.resolveKey(nodeId1), 'user:1', 'reverse key lookup works');
  });

  test('direct relation authorization', () => {
    const arbiter = new Arbiter();
    
    arbiter.addNode('user:1', 'user');
    arbiter.addNode('resource:1', 'resource');
    arbiter.setRelationConfig('owner', { type: 'direct' });
    
    arbiter.addRelation('user:1', 'owner', 'resource:1', 1.0);
    
    const result = arbiter.check('user:1', 'owner', 'resource:1');
    assert.strictEqual(result.possibility, 1.0, 'owner relation grants access');
    assert.strictEqual(result.reason, 'direct_match', 'reason is direct_match');
  });

  test('absence of relation denies access', () => {
    const arbiter = new Arbiter();
    
    arbiter.addNode('user:1', 'user');
    arbiter.addNode('resource:1', 'resource');
    arbiter.addNode('user:2', 'user');
    arbiter.setRelationConfig('owner', { type: 'direct' });
    
    arbiter.addRelation('user:1', 'owner', 'resource:1', 1.0);
    
    const result = arbiter.check('user:2', 'owner', 'resource:1');
    assert.strictEqual(result.possibility, 0.0, 'non-owner denied');
    assert.strictEqual(result.reason, 'no_relation', 'reason is no_relation');
  });

  test('node data storage and retrieval', () => {
    const arbiter = new Arbiter();
    
    arbiter.addNode('user:1', 'user', { tier: 'premium', level: 5 });
    const data = arbiter.getNodeData('user:1');
    
    assert.strictEqual(data.tier, 'premium');
    assert.strictEqual(data.level, 5);
  });

  test('node data update', () => {
    const arbiter = new Arbiter();
    
    arbiter.addNode('user:1', 'user', { tier: 'premium' });
    arbiter.updateNodeData('user:1', { tier: 'enterprise', level: 10 });
    
    const data = arbiter.getNodeData('user:1');
    assert.strictEqual(data.tier, 'enterprise');
    assert.strictEqual(data.level, 10);
  });

  test('multiple relations between different node types', () => {
    const arbiter = new Arbiter();
    
    arbiter.addNode('user:1', 'user');
    arbiter.addNode('group:1', 'group');
    arbiter.addNode('resource:1', 'resource');
    
    arbiter.setRelationConfig('member', { type: 'direct' });
    arbiter.setRelationConfig('can_view', { type: 'direct' });
    
    arbiter.addRelation('user:1', 'member', 'group:1', 1.0);
    arbiter.addRelation('group:1', 'can_view', 'resource:1', 1.0);
    
    const memberResult = arbiter.check('user:1', 'member', 'group:1');
    const viewResult = arbiter.check('group:1', 'can_view', 'resource:1');
    
    assert.strictEqual(memberResult.possibility, 1.0);
    assert.strictEqual(viewResult.possibility, 1.0);
  });
});
