/// <cts-enable />
/**
 * Test Pattern: Counter
 *
 * Tests the core functionality of the counter pattern:
 * - Initial state (value defaults to 0)
 * - Increment via module-scope handler
 * - Decrement via pattern-body action
 * - Multiple increments/decrements
 * - Negative values
 *
 * Run: deno task ct test packages/patterns/counter/counter.test.tsx --verbose
 */
import { action, computed, pattern } from "commontools";
import Counter from "./counter.tsx";

export default pattern(() => {
  // Instantiate the counter pattern with default value (0)
  const counter = Counter({});

  // Also test with a non-zero initial value
  const counterStartingAt5 = Counter({ value: 5 });

  // ==========================================================================
  // Actions - using action() to trigger stream sends
  // ==========================================================================

  // Increment once (tests module-scope handler)
  const action_increment = action(() => {
    counter.increment.send();
  });

  // Increment again
  const action_increment_again = action(() => {
    counter.increment.send();
  });

  // Decrement once (tests pattern-body action)
  const action_decrement = action(() => {
    counter.decrement.send();
  });

  // Decrement multiple times to go negative
  const action_decrement_twice = action(() => {
    counter.decrement.send();
    counter.decrement.send();
  });

  // Test the counter that starts at 5
  const action_decrement_from_5 = action(() => {
    counterStartingAt5.decrement.send();
  });

  const action_increment_from_5 = action(() => {
    counterStartingAt5.increment.send();
  });

  // ==========================================================================
  // Assertions - computed booleans
  // ==========================================================================

  // Initial state assertions
  const assert_initial_value_is_0 = computed(() => counter.value === 0);
  const assert_initial_value_is_5 = computed(() =>
    counterStartingAt5.value === 5
  );

  // After first increment
  const assert_value_is_1 = computed(() => counter.value === 1);

  // After second increment
  const assert_value_is_2 = computed(() => counter.value === 2);

  // After decrement (back to 1)
  const assert_value_is_1_again = computed(() => counter.value === 1);

  // After decrementing twice more (goes to -1)
  const assert_value_is_negative_1 = computed(() => counter.value === -1);

  // Counter starting at 5: after decrement should be 4
  const assert_from_5_is_4 = computed(() => counterStartingAt5.value === 4);

  // Counter starting at 5: after increment should be 5 again
  const assert_from_5_back_to_5 = computed(() =>
    counterStartingAt5.value === 5
  );

  // After another increment should be 6
  const action_increment_to_6 = action(() => {
    counterStartingAt5.increment.send();
  });
  const assert_from_5_is_6 = computed(() => counterStartingAt5.value === 6);

  // ==========================================================================
  // Test Sequence
  // ==========================================================================
  return {
    tests: [
      // === Test 1: Initial state ===
      { assertion: assert_initial_value_is_0 },
      { assertion: assert_initial_value_is_5 },

      // === Test 2: Increment (module-scope handler) ===
      { action: action_increment },
      { assertion: assert_value_is_1 },

      // === Test 3: Increment again ===
      { action: action_increment_again },
      { assertion: assert_value_is_2 },

      // === Test 4: Decrement (pattern-body action) ===
      { action: action_decrement },
      { assertion: assert_value_is_1_again },

      // === Test 5: Decrement to negative ===
      { action: action_decrement_twice },
      { assertion: assert_value_is_negative_1 },

      // === Test 6: Counter with initial value of 5 ===
      { action: action_decrement_from_5 },
      { assertion: assert_from_5_is_4 },

      // === Test 7: Increment back up ===
      { action: action_increment_from_5 },
      { assertion: assert_from_5_back_to_5 },

      // === Test 8: Increment past initial value ===
      { action: action_increment_to_6 },
      { assertion: assert_from_5_is_6 },
    ],
    // Expose subjects for debugging
    counter,
    counterStartingAt5,
  };
});
