/**
 * Test Bilattice Integration with Existing Possibilistic Infrastructure
 * 
 * This test demonstrates how bilattice orderings are integrated into our existing
 * rule system while maintaining compatibility with possibilistic reasoning.
 */

import { test, describe } from 'node:test';
import assert from 'node:assert';
import {
  QualitativeScale,
  QualitativeCapacity,
  BilatticeOrderings,
  getSetKey
} from '../../src/qualitative/index.js';

describe('Bilattice Integration with Possibilistic Infrastructure', () => {
  
  test('should demonstrate BaseRule bilattice-enhanced evidence combination', () => {
    const scale = QualitativeScale.fivePoint();
    const stateSpace = ['evidence1', 'evidence2', 'evidence3'];
    
    // Create a capacity for bilattice analysis
    const qmt = new Map();
    qmt.set(getSetKey(new Set(['evidence1'])), 0.75);  // High belief evidence
    qmt.set(getSetKey(new Set(['evidence2'])), 0.5);   // Medium belief evidence
    qmt.set(getSetKey(new Set(['evidence3'])), 0.25);  // Low belief evidence
    qmt.set(getSetKey(new Set(['evidence1', 'evidence2'])), 1);  // Combined evidence
    
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    // Simulate collected values from rule evaluation - using valid fivePoint scale values
    const collectedValues = [
      {
        value: 0.75, // Valid fivePoint scale value
        possibility: 0.75, // Valid fivePoint scale value
        path: ['user', 'relation1'],
        source: { entityKey: 'user1', relation: 'score', step: 0 },
        metadata: { timestamp: Date.now(), reliability: 0.9 }
      },
      {
        value: 0.5, // Valid fivePoint scale value
        possibility: 0.5, // Valid fivePoint scale value
        path: ['user', 'relation2'],
        source: { entityKey: 'user2', relation: 'rating', step: 1 },
        metadata: { timestamp: Date.now(), reliability: 0.8 }
      },
      {
        value: 0.25, // Valid fivePoint scale value
        possibility: 0.25, // Valid fivePoint scale value
        path: ['user', 'relation3'],
        source: { entityKey: 'user3', relation: 'feedback', step: 2 },
        metadata: { timestamp: Date.now(), reliability: 0.7 }
      }
    ];
    
    // Test information-based evidence selection
    const epistemicPairs = collectedValues.map(cv => ({
      belief: cv.possibility,
      disbelief: 1 - cv.possibility
    }));
    
    // Create propositions for bilattice analysis
    const propositions = collectedValues.map((cv, index) => [`evidence${index + 1}`]);
    
    const mostInformative = BilatticeOrderings.findMostInformative(propositions, capacity);
    
    // The most informative evidence should be the one with highest belief AND disbelief
    // Evidence 1: belief=0.75, disbelief=0.25
    // Evidence 2: belief=0.5, disbelief=0.5  
    // Evidence 3: belief=0.25, disbelief=0.75
    // Evidence 1 and 2 are incomparable in information ordering (neither dominates)
    // The algorithm picks the first one (evidence 1) as default
    assert.strictEqual(mostInformative.epistemic.belief, 0.75);
    // Disbelief = capacity of the complement: max focal subset of
    // {evidence2, evidence3} is {evidence2}=0.5.
    assert.strictEqual(mostInformative.epistemic.disbelief, 0.5);
    assert.strictEqual(mostInformative.rank, 1);
  });
  
  test('should demonstrate qualitative relational comparator with bilattice reasoning', () => {
    const scale = QualitativeScale.fivePoint();
    
    // Simulate blurred values from qualitative decay
    const blurredValues = [
      {
        interval: { lower: 0.5, upper: 0.75 },
        possibility: 0.75,
        originalValue: 0.75,
        originalPossibility: 1.0,
        timestamp: Date.now(),
        relation: 'score',
        meta: { periodsElapsed: 1, blurSteps: 1 }
      },
      {
        interval: { lower: 0.25, upper: 0.5 },
        possibility: 0.5,
        originalValue: 0.5,
        originalPossibility: 0.8,
        timestamp: Date.now(),
        relation: 'rating',
        meta: { periodsElapsed: 2, blurSteps: 2 }
      }
    ];
    
    // Test epistemic comparison of blurred values
    const epistemicPairs = blurredValues.map(bv => ({
      belief: bv.possibility,
      disbelief: 1 - bv.possibility
    }));
    
    // Create a simple capacity for comparison
    const stateSpace = ['blurred1', 'blurred2'];
    const qmt = new Map();
    qmt.set(getSetKey(new Set(['blurred1'])), 0.75);
    qmt.set(getSetKey(new Set(['blurred2'])), 0.5);
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    const comparison = BilatticeOrderings.compareEpistemicStatus(
      ['blurred1'], ['blurred2'], capacity
    );
    
    // blurred1 should be more true than blurred2 (higher capacity value)
    assert.ok(comparison.truthOrdering);
    assert.strictEqual(comparison.relationship, 'A more true than B');
  });
  
  test('should demonstrate defeasible logic with bilattice reasoning', () => {
    const scale = QualitativeScale.tenPoint();
    
    // Simulate evidence from different rule types in defeasible logic
    const strictEvidence = {
      value: 1.0,
      possibility: 1.0,
      path: ['strict_rule'],
      source: { entityKey: 'system', relation: 'strict_check', step: 0 },
      metadata: { timestamp: Date.now(), reliability: 1.0, ruleType: 'strict' }
    };
    
    const defeasibleEvidence = {
      value: 0.8,
      possibility: 0.8,
      path: ['defeasible_rule'],
      source: { entityKey: 'user', relation: 'user_check', step: 1 },
      metadata: { timestamp: Date.now(), reliability: 0.9, ruleType: 'defeasible' }
    };
    
    const defeaterEvidence = {
      value: 0.6,
      possibility: 0.6,
      path: ['defeater_rule'],
      source: { entityKey: 'security', relation: 'security_check', step: 2 },
      metadata: { timestamp: Date.now(), reliability: 0.8, ruleType: 'defeater' }
    };
    
    const allEvidence = [strictEvidence, defeasibleEvidence, defeaterEvidence];
    
    // Create capacity representing the defeasible logic structure
    const stateSpace = ['strict', 'defeasible', 'defeater'];
    const qmt = new Map();
    qmt.set(getSetKey(new Set(['strict'])), 1.0);      // Strict rules have highest priority
    qmt.set(getSetKey(new Set(['defeasible'])), 0.8);  // Defeasible rules have medium priority
    qmt.set(getSetKey(new Set(['defeater'])), 0.6);    // Defeaters have lower priority
    qmt.set(getSetKey(new Set(['strict', 'defeasible'])), 1.0);  // Strict + defeasible = strict wins
    qmt.set(getSetKey(new Set(['strict', 'defeater'])), 1.0);    // Strict + defeater = strict wins
    qmt.set(getSetKey(new Set(['defeasible', 'defeater'])), 0.8); // Defeasible + defeater = defeasible wins
    
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    // Test information ordering for defeasible logic
    const epistemicPairs = allEvidence.map(ev => ({
      belief: ev.possibility,
      disbelief: 1 - ev.possibility
    }));
    
    // Create propositions for bilattice analysis (must match the capacity state space)
    const propositions = [['strict'], ['defeasible'], ['defeater']];
    
    const informationRanking = BilatticeOrderings.rankByInformation(propositions, capacity);
    
    // Strict evidence should rank highest in information ordering
    const strictRank = informationRanking.find(r => r.epistemic.belief === 1.0)?.rank;
    const defeasibleRank = informationRanking.find(r => r.epistemic.belief === 0.8)?.rank;
    const defeaterRank = informationRanking.find(r => r.epistemic.belief === 0.6)?.rank;
    
    assert.ok(strictRank <= defeasibleRank);
    assert.ok(defeasibleRank <= defeaterRank);
  });
  
  test('should demonstrate chain rule with epistemic path analysis', () => {
    const scale = QualitativeScale.tenPoint();
    
    // Simulate collected values from a chain traversal
    const chainValues = [
      {
        value: 0.9,
        possibility: 0.9,
        path: ['user', 'account', 'balance'],
        source: { entityKey: 'account1', relation: 'balance', step: 2 },
        metadata: { timestamp: Date.now(), reliability: 0.95, pathPossibility: 0.9 }
      },
      {
        value: 0.7,
        possibility: 0.7,
        path: ['user', 'account', 'credit'],
        source: { entityKey: 'account2', relation: 'credit', step: 2 },
        metadata: { timestamp: Date.now(), reliability: 0.85, pathPossibility: 0.7 }
      },
      {
        value: 0.5,
        possibility: 0.5,
        path: ['user', 'account', 'debt'],
        source: { entityKey: 'account3', relation: 'debt', step: 2 },
        metadata: { timestamp: Date.now(), reliability: 0.75, pathPossibility: 0.5 }
      }
    ];
    
    // Create capacity for path-based epistemic analysis
    const stateSpace = ['path1', 'path2', 'path3'];
    const qmt = new Map();
    qmt.set(getSetKey(new Set(['path1'])), 0.9);  // High confidence path
    qmt.set(getSetKey(new Set(['path2'])), 0.7);  // Medium confidence path
    qmt.set(getSetKey(new Set(['path3'])), 0.5);  // Low confidence path
    qmt.set(getSetKey(new Set(['path1', 'path2'])), 1.0);  // Combined high-confidence paths
    
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    // Test truth ordering for path selection
    const pathPropositions = [
      ['path1'], ['path2'], ['path3']
    ];
    
    const truthRanking = BilatticeOrderings.rankByTruth(pathPropositions, capacity);
    
    // Path1 should rank highest in truth ordering (highest capacity value)
    const path1Rank = truthRanking.find(r => r.capacity === 0.9)?.rank;
    const path2Rank = truthRanking.find(r => r.capacity === 0.7)?.rank;
    const path3Rank = truthRanking.find(r => r.capacity === 0.5)?.rank;
    
    assert.strictEqual(path1Rank, 1);
    assert.ok(path2Rank > path1Rank);
    assert.ok(path3Rank > path2Rank);
  });
  
  test('should demonstrate hybrid epistemic reasoning', () => {
    const scale = QualitativeScale.tenPoint();
    
    // Simulate mixed evidence from different sources
    const mixedEvidence = [
      {
        value: 0.8,
        possibility: 0.8,
        path: ['direct_evidence'],
        source: { entityKey: 'direct', relation: 'observation', step: 0 },
        metadata: { timestamp: Date.now(), reliability: 0.9, sourceType: 'direct' }
      },
      {
        value: 0.6,
        possibility: 0.6,
        path: ['inferred_evidence'],
        source: { entityKey: 'inference', relation: 'deduction', step: 1 },
        metadata: { timestamp: Date.now(), reliability: 0.7, sourceType: 'inferred' }
      },
      {
        value: 0.4,
        possibility: 0.4,
        path: ['similarity_evidence'],
        source: { entityKey: 'similarity', relation: 'analogy', step: 2 },
        metadata: { timestamp: Date.now(), reliability: 0.6, sourceType: 'similarity' }
      }
    ];
    
    // Create capacity for hybrid analysis
    const stateSpace = ['direct', 'inferred', 'similarity'];
    const qmt = new Map();
    qmt.set(getSetKey(new Set(['direct'])), 0.8);      // Direct evidence has highest reliability
    qmt.set(getSetKey(new Set(['inferred'])), 0.6);    // Inferred evidence has medium reliability
    qmt.set(getSetKey(new Set(['similarity'])), 0.4);  // Similarity evidence has lowest reliability
    qmt.set(getSetKey(new Set(['direct', 'inferred'])), 0.9);  // Direct + inferred = high confidence
    qmt.set(getSetKey(new Set(['direct', 'similarity'])), 0.8); // Direct + similarity = direct dominates
    qmt.set(getSetKey(new Set(['inferred', 'similarity'])), 0.6); // Inferred + similarity = inferred dominates
    
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    // Test comprehensive epistemic comparison
    const epistemicPairs = mixedEvidence.map(ev => ({
      belief: ev.possibility,
      disbelief: 1 - ev.possibility
    }));
    
    // Create propositions for bilattice analysis (must match the capacity state space)
    const propositions = [['direct'], ['inferred'], ['similarity']];
    
    const informationRanking = BilatticeOrderings.rankByInformation(propositions, capacity);
    const truthRanking = BilatticeOrderings.rankByTruth(propositions, capacity);
    
    // Direct evidence should rank highest in both orderings
    const directInfoRank = informationRanking.find(r => r.epistemic.belief === 0.8)?.rank;
    const directTruthRank = truthRanking.find(r => r.capacity === 0.8)?.rank;
    
    assert.strictEqual(directInfoRank, 1);
    assert.strictEqual(directTruthRank, 1);
    
    // Test comprehensive comparison
    const comparison = BilatticeOrderings.compareEpistemicStatus(
      ['direct'], ['inferred'], capacity
    );
    
    assert.ok(comparison.truthOrdering);
    assert.strictEqual(comparison.relationship, 'A more true than B');
  });
  
  test('should maintain backward compatibility with existing possibilistic infrastructure', () => {
    const scale = QualitativeScale.tenPoint();
    
    // Test that bilattice reasoning can be disabled and standard OWA fusion still works
    const standardEvidence = [
      { value: 0.8, possibility: 0.8, path: ['evidence1'], source: {}, metadata: {} },
      { value: 0.6, possibility: 0.6, path: ['evidence2'], source: {}, metadata: {} },
      { value: 0.4, possibility: 0.4, path: ['evidence3'], source: {}, metadata: {} }
    ];
    
    // Test standard OWA fusion (bilattice disabled)
    const epistemicPairs = standardEvidence.map(ev => ({
      belief: ev.possibility,
      disbelief: 1 - ev.possibility
    }));
    
    // Standard max operation should select the highest value
    const maxValue = Math.max(...standardEvidence.map(ev => ev.possibility));
    assert.strictEqual(maxValue, 0.8);
    
    // Test that bilattice reasoning can be enabled when needed
    const stateSpace = ['ev1', 'ev2', 'ev3'];
    const qmt = new Map();
    qmt.set(getSetKey(new Set(['ev1'])), 0.8);
    qmt.set(getSetKey(new Set(['ev2'])), 0.6);
    qmt.set(getSetKey(new Set(['ev3'])), 0.4);
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    // Create propositions for bilattice analysis
    const propositions = standardEvidence.map((ev, index) => [`ev${index + 1}`]);
    
    const mostInformative = BilatticeOrderings.findMostInformative(propositions, capacity);
    
    // Epistemic pairs from the capacity:
    // ev1 ({ev1}): belief=0.8,  disbelief=gamma({ev2,ev3})=0.6
    // ev2 ({ev2}): belief=0.6,  disbelief=gamma({ev1,ev3})=0.8
    // ev3 ({ev3}): belief=0.4,  disbelief=gamma({ev1,ev2})=0.8
    // ev1 dominates in belief; the algorithm keeps the first best (ev1).
    assert.strictEqual(mostInformative.epistemic.belief, 0.8);
    assert.strictEqual(mostInformative.epistemic.disbelief, 0.6);
  });
});
