/**
 * Test Bilattice Orderings for Evidential Reasoning
 * 
 * This test demonstrates the bilattice orderings (≥ᵢ, ≥ₜ) for comparing
 * epistemic status of propositions in qualitative capacity systems.
 */

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

describe('Bilattice Orderings', () => {
  test('should implement information ordering correctly', () => {
    const scale = QualitativeScale.fivePoint();
    
    // Test information ordering: (c₁, c₁') ≥ᵢ (c₂, c₂') ⟺ c₁ ≥ c₂ and c₁' ≥ c₂'
    const epistemic1 = { belief: 0.75, disbelief: 0.5 };
    const epistemic2 = { belief: 0.5, disbelief: 0.25 };
    const epistemic3 = { belief: 0.75, disbelief: 0.25 };
    
    // epistemic1 should be more informative than epistemic2
    assert.ok(BilatticeOrderings.informationOrdering(epistemic1, epistemic2, scale));
    
    // epistemic1 should be more informative than epistemic3 (higher disbelief)
    assert.ok(BilatticeOrderings.informationOrdering(epistemic1, epistemic3, scale));
    
    // epistemic3 should NOT be more informative than epistemic1 (lower disbelief)
    assert.ok(!BilatticeOrderings.informationOrdering(epistemic3, epistemic1, scale));
  });

  test('should implement truth ordering correctly', () => {
    const scale = QualitativeScale.fivePoint();
    const stateSpace = ['s1', 's2', 's3'];
    
    // Create a capacity where s1 has high belief, s2 has medium belief
    const qmt = new Map();
    qmt.set(new Set(['s1']), 0.75);  // High belief in s1
    qmt.set(new Set(['s2']), 0.5);   // Medium belief in s2
    qmt.set(new Set(['s1', 's2']), 1);  // Full belief in s1 OR s2
    
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    const propositionA = ['s1'];  // High belief
    const propositionB = ['s2'];  // Medium belief
    
    // A should be more true than B: γ(A) ≥ γ(B) and γ(Bᶜ) ≥ γ(Aᶜ)
    assert.ok(BilatticeOrderings.truthOrdering(propositionA, propositionB, capacity));
    
    // B should NOT be more true than A
    assert.ok(!BilatticeOrderings.truthOrdering(propositionB, propositionA, capacity));
  });

  test('should compare epistemic status comprehensively', () => {
    const scale = QualitativeScale.fivePoint();
    const stateSpace = ['s1', 's2', 's3'];
    
    // Create a capacity with different belief levels
    const qmt = new Map();
    qmt.set(new Set(['s1']), 0.75);
    qmt.set(new Set(['s2']), 0.5);
    qmt.set(new Set(['s3']), 0.25);
    qmt.set(new Set(['s1', 's2']), 1);
    qmt.set(new Set(['s1', 's2', 's3']), 1);
    
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    const propositionA = ['s1'];
    const propositionB = ['s2'];
    
    const comparison = BilatticeOrderings.compareEpistemicStatus(propositionA, propositionB, capacity);
    
    // Check that we get a comprehensive comparison
    assert.ok(comparison.propositionA);
    assert.ok(comparison.propositionB);
    assert.ok(typeof comparison.informationOrdering === 'boolean');
    assert.ok(typeof comparison.truthOrdering === 'boolean');
    assert.ok(typeof comparison.relationship === 'string');
    assert.ok(typeof comparison.analysis === 'string');
    
    // A should be more true than B, but not more informative
    assert.ok(!comparison.informationOrdering);
    assert.ok(comparison.truthOrdering);
    assert.strictEqual(comparison.relationship, 'A more true than B');
  });

  test('should find most informative proposition', () => {
    const scale = QualitativeScale.fivePoint();
    const stateSpace = ['s1', 's2', 's3'];
    
    // Create a capacity with varying belief levels
    const qmt = new Map();
    qmt.set(new Set(['s1']), 0.75);
    qmt.set(new Set(['s2']), 0.5);
    qmt.set(new Set(['s3']), 0.25);
    qmt.set(new Set(['s1', 's2']), 1);
    qmt.set(new Set(['s1', 's2', 's3']), 1);
    
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    const propositions = [['s1'], ['s2'], ['s3']];
    
    const mostInformative = BilatticeOrderings.findMostInformative(propositions, capacity);
    
    // s1 should be most informative (highest belief and disbelief)
    assert.deepStrictEqual(mostInformative.proposition, ['s1']);
    assert.strictEqual(mostInformative.rank, 1);
    assert.strictEqual(mostInformative.total, 3);
    assert.ok(mostInformative.analysis.includes('Most informative'));
  });

  test('should find most true proposition', () => {
    const scale = QualitativeScale.fivePoint();
    const stateSpace = ['s1', 's2', 's3'];
    
    // Create a capacity with varying belief levels
    const qmt = new Map();
    qmt.set(new Set(['s1']), 0.75);
    qmt.set(new Set(['s2']), 0.5);
    qmt.set(new Set(['s3']), 0.25);
    qmt.set(new Set(['s1', 's2']), 1);
    qmt.set(new Set(['s1', 's2', 's3']), 1);
    
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    const propositions = [['s1'], ['s2'], ['s3']];
    
    const mostTrue = BilatticeOrderings.findMostTrue(propositions, capacity);
    
    // s1 should be most true (highest capacity value)
    assert.deepStrictEqual(mostTrue.proposition, ['s1']);
    assert.strictEqual(mostTrue.capacity, 0.75);
    assert.strictEqual(mostTrue.rank, 1);
    assert.strictEqual(mostTrue.total, 3);
    assert.ok(mostTrue.analysis.includes('Most true'));
  });

  test('should rank propositions by information content', () => {
    const scale = QualitativeScale.fivePoint();
    const stateSpace = ['s1', 's2', 's3'];
    
    // Create a capacity with varying belief levels
    const qmt = new Map();
    qmt.set(new Set(['s1']), 0.75);
    qmt.set(new Set(['s2']), 0.5);
    qmt.set(new Set(['s3']), 0.25);
    qmt.set(new Set(['s1', 's2']), 1);
    qmt.set(new Set(['s1', 's2', 's3']), 1);
    
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    const propositions = [['s1'], ['s2'], ['s3']];
    
    const ranking = BilatticeOrderings.rankByInformation(propositions, capacity);
    
    // Should have 3 ranked propositions
    assert.strictEqual(ranking.length, 3);
    
    // Check ranking structure
    for (let i = 0; i < ranking.length; i++) {
      assert.strictEqual(ranking[i].rank, i + 1);
      assert.ok(ranking[i].proposition);
      assert.ok(ranking[i].epistemic);
      assert.ok(ranking[i].analysis);
    }
    
    // s1 should be ranked first (most informative)
    assert.deepStrictEqual(ranking[0].proposition, ['s1']);
  });

  test('should rank propositions by truth content', () => {
    const scale = QualitativeScale.fivePoint();
    const stateSpace = ['s1', 's2', 's3'];
    
    // Create a capacity with varying belief levels
    const qmt = new Map();
    qmt.set(new Set(['s1']), 0.75);
    qmt.set(new Set(['s2']), 0.5);
    qmt.set(new Set(['s3']), 0.25);
    qmt.set(new Set(['s1', 's2']), 1);
    qmt.set(new Set(['s1', 's2', 's3']), 1);
    
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    const propositions = [['s1'], ['s2'], ['s3']];
    
    const ranking = BilatticeOrderings.rankByTruth(propositions, capacity);
    
    // Should have 3 ranked propositions
    assert.strictEqual(ranking.length, 3);
    
    // Check ranking structure
    for (let i = 0; i < ranking.length; i++) {
      assert.strictEqual(ranking[i].rank, i + 1);
      assert.ok(ranking[i].proposition);
      assert.ok(typeof ranking[i].capacity === 'number');
      assert.ok(ranking[i].analysis);
    }
    
    // s1 should be ranked first (most true)
    assert.deepStrictEqual(ranking[0].proposition, ['s1']);
    assert.strictEqual(ranking[0].capacity, 0.75);
  });

  test('should handle edge cases correctly', () => {
    const scale = QualitativeScale.fivePoint();
    const stateSpace = ['s1', 's2'];
    
    // Create a simple capacity
    const qmt = new Map();
    qmt.set(new Set(['s1']), 0.5);
    qmt.set(new Set(['s1', 's2']), 1);
    
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    // Test with single proposition
    const singleProposition = [['s1']];
    
    const mostInformative = BilatticeOrderings.findMostInformative(singleProposition, capacity);
    const mostTrue = BilatticeOrderings.findMostTrue(singleProposition, capacity);
    
    assert.deepStrictEqual(mostInformative.proposition, ['s1']);
    assert.strictEqual(mostInformative.rank, 1);
    assert.strictEqual(mostInformative.total, 1);
    
    assert.deepStrictEqual(mostTrue.proposition, ['s1']);
    assert.strictEqual(mostTrue.rank, 1);
    assert.strictEqual(mostTrue.total, 1);
  });

  test('should handle incomparable propositions', () => {
    const scale = QualitativeScale.fivePoint();
    const stateSpace = ['s1', 's2', 's3'];
    
    // Create a capacity where propositions are incomparable
    const qmt = new Map();
    qmt.set(new Set(['s1']), 0.75);  // High belief, low disbelief
    qmt.set(new Set(['s2']), 0.5);   // Medium belief, medium disbelief
    qmt.set(new Set(['s1', 's2']), 1);
    qmt.set(new Set(['s1', 's2', 's3']), 1);
    
    const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
    
    const propositionA = ['s1'];
    const propositionB = ['s2'];
    
    const comparison = BilatticeOrderings.compareEpistemicStatus(propositionA, propositionB, capacity);
    
    // Should identify the relationship correctly
    assert.ok(typeof comparison.relationship === 'string');
    assert.ok(comparison.relationship !== '');
  });
});
