import { test, describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { setupChainRuleTestGraph } from './helpers.js';

describe('ChainRule Comprehensive Tests', () => {

  describe('Fast Path and Performance Optimization', () => {
    it('supports early exit with minAllowPossibility threshold', () => {
      const arbiter = setupChainRuleTestGraph();

      arbiter.setRelationConfig('quick_access_check', {
        type: 'chain',
        steps: [
          { relation: 'member_of', direction: 'out' },
          { relation: 'manages', direction: 'out' }
        ]
      });

      // Test with fast path enabled and low threshold
      const result = arbiter.check('user:alice', 'quick_access_check', 'project:web-app', {
        fastPath: true,
        minAllowPossibility: 0.5  // Exit early if possibility >= 0.5
      });

      assert.equal(result.possibility, 1);
      assert.equal(result.reason, 'allow_threshold_met');
    });

    it('supports early exit with maxDenyPossibility threshold', () => {
      const arbiter = setupChainRuleTestGraph();

      arbiter.setRelationConfig('deny_check', {
        type: 'chain',
        steps: [
          { relation: 'member_of', direction: 'out' },
          { relation: 'manages', direction: 'out' }
        ]
      });

      // Test denial with fast path
      const result = arbiter.check('user:alice', 'deny_check', 'project:mobile-app', {
        fastPath: true,
        maxDenyPossibility: 0.8   // Exit early if denial >= 0.8
      });

      assert.equal(result.possibility, 0);
      assert.equal(result.reason, 'no_chain_path_found');
    });
  });

  describe('Comparison with Other Rules', () => {
    it('compares ChainRule vs ParentRule performance', () => {
      const arbiter = setupChainRuleTestGraph();

      // Set up equivalent rules using ChainRule and ParentRule
      arbiter.setRelationConfig('chain_parent_check', {
        type: 'chain',
        steps: [
          { relation: 'manages', direction: 'in' },   // project ← group
          { relation: 'member_of', direction: 'in' }  // group ← user
        ]
      });

      arbiter.setRelationConfig('traditional_parent_check', {
        type: 'parent',
        parentRelation: 'manages',
        relation: 'member_of',
        reverse: true
      });

      const startTime1 = Date.now();
      const chainResult = arbiter.check('project:web-app', 'chain_parent_check', 'user:alice');
      const chainTime = Date.now() - startTime1;

      const startTime2 = Date.now();
      const parentResult = arbiter.check('project:web-app', 'traditional_parent_check', 'user:alice');
      const parentTime = Date.now() - startTime2;

      if (process.env.TEST_DEBUG === '1') console.log('ChainRule result:', chainResult.possibility);
      if (process.env.TEST_DEBUG === '1') console.log('ParentRule result:', parentResult.possibility);

      // ChainRule should succeed (Alice is member of engineering, which manages web-app)
      assert.equal(chainResult.possibility, 1);

      // ParentRule might have different semantics - just verify it returns a valid result
      assert.ok(typeof parentResult.possibility === 'number');

      if (process.env.TEST_DEBUG === '1') console.log(`ChainRule time: ${chainTime}ms, ParentRule time: ${parentTime}ms`);

      // ChainRule should be reasonably performant
      assert.ok(chainTime < 100); // Should complete in reasonable time
    });

    it('compares ChainRule vs MultiHopRule for path finding', () => {
      const arbiter = setupChainRuleTestGraph();

      // ChainRule: specific path
      arbiter.setRelationConfig('chain_access', {
        type: 'chain',
        steps: [
          { relation: 'member_of', direction: 'out' },
          { relation: 'belongs_to', direction: 'out' },
          { relation: 'has_access_level', direction: 'out' }
        ]
      });

      // MultiHopRule: flexible path finding
      arbiter.setRelationConfig('multihop_access', {
        type: 'multi_hop',
        relation: 'member_of',
        maxDepth: 3,
        pathAggregation: 'max'
      });

      const chainResult = arbiter.check('user:alice', 'chain_access', 'access:level-5');
      const multihopResult = arbiter.check('user:alice', 'multihop_access', 'access:level-5');

      // ChainRule should give precise result for defined path
      assert.equal(chainResult.possibility, 1);

      // MultiHopRule might give different result based on path exploration
      if (process.env.TEST_DEBUG === '1') console.log('Chain vs MultiHop results:', {
        chain: chainResult.possibility,
        multihop: multihopResult.possibility
      });
    });

    it('demonstrates ChainRule semantic clarity vs other approaches', () => {
      const arbiter = setupChainRuleTestGraph();

      // ChainRule: explicit semantic path
      arbiter.setRelationConfig('semantic_chain', {
        type: 'chain',
        steps: [
          { relation: 'member_of', direction: 'out' },
          { relation: 'manages', direction: 'out' },
          { relation: 'has_budget', direction: 'out' }
        ],
        extractValues: true,
        extractFrom: 2,
        extractRelation: 'has_budget',
        valueAggregation: 'sum'
      });

      const result = arbiter.check('user:alice', 'semantic_chain', 'budget:tech-2024');

      // Should provide clear semantic meaning:
      // "user's budget access through group project management"
      assert.equal(result.possibility, 1);

      // Values are internal only, not exposed in authorization results
      assert.equal(result.value, undefined);

      if (process.env.TEST_DEBUG === '1') console.log('Semantic chain result:', {
        access: result.possibility,
        meaning: 'user → group → project → budget'
      });
    });
  });
});
