import { ApplicationRef, effect } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { describe, expect, it } from 'vitest';
import { createStore } from './store';

describe('createStore', () => {
  it('applies the pure update on dispatch', () => {
    const store = createStore(0, (n: number, m: number) => n + m);
    store.dispatch(5);
    store.dispatch(3);
    expect(store.model()).toBe(8);
  });

  // Regression: an effect that dispatches must NOT re-run because of its own write.
  // dispatch used to read `model()` reactively (`set(update(model(), msg))`), so an
  // effect calling dispatch subscribed to `model` and looped forever, livelocking the
  // main thread (crashed the upload wizards). With `.update` the read is untracked.
  it('dispatch from inside an effect does not self-loop', () => {
    const store = createStore(0, (n: number, _m: 'inc') => n + 1);
    let runs = 0;
    TestBed.runInInjectionContext(() => {
      effect(() => {
        runs++;
        if (runs < 100) store.dispatch('inc'); // bounded so the buggy version can't hang the test
      });
    });
    TestBed.inject(ApplicationRef).tick(); // flush effects

    expect(runs).toBe(1); // effect ran once; its own dispatch did not retrigger it
    expect(store.model()).toBe(1);
  });
});
