import { describe, expect, it, vi } from 'vitest';
import { connectSaveProtection } from '../save-protection';

describe('connectSaveProtection', () => {
  it('tracks pending or failed saves and clears protection after success', () => {
    let dirty = false;
    let listener: (() => void) | undefined;
    const unsubscribe = vi.fn();
    const setUnsavedChanges = vi.fn();
    const cleanup = connectSaveProtection(
      {
        hasPendingOrFailedSave: () => dirty,
        subscribeToSaveStatus: (nextListener) => {
          listener = nextListener;
          return unsubscribe;
        },
      },
      { setUnsavedChanges },
    );

    expect(setUnsavedChanges).toHaveBeenLastCalledWith(false);

    dirty = true;
    listener?.();
    expect(setUnsavedChanges).toHaveBeenLastCalledWith(true);

    dirty = false;
    listener?.();
    expect(setUnsavedChanges).toHaveBeenLastCalledWith(false);

    cleanup();
    expect(unsubscribe).toHaveBeenCalledOnce();
    expect(setUnsavedChanges).toHaveBeenLastCalledWith(false);
  });
  it('protects navigation while any editor source is dirty', () => {
    let markdownDirty = false;
    let latexDirty = false;
    const markdownListeners = new Set<() => void>();
    const latexListeners = new Set<() => void>();
    const setUnsavedChanges = vi.fn();

    const cleanup = connectSaveProtection(
      [
        {
          hasPendingOrFailedSave: () => markdownDirty,
          subscribeToSaveStatus: (listener) => {
            markdownListeners.add(listener);
            return () => markdownListeners.delete(listener);
          },
        },
        {
          hasPendingOrFailedSave: () => latexDirty,
          subscribeToSaveStatus: (listener) => {
            latexListeners.add(listener);
            return () => latexListeners.delete(listener);
          },
        },
      ],
      { setUnsavedChanges },
    );

    latexDirty = true;
    for (const listener of latexListeners) listener();
    expect(setUnsavedChanges).toHaveBeenLastCalledWith(true);

    markdownDirty = true;
    latexDirty = false;
    for (const listener of latexListeners) listener();
    expect(setUnsavedChanges).toHaveBeenLastCalledWith(true);

    markdownDirty = false;
    for (const listener of markdownListeners) listener();
    expect(setUnsavedChanges).toHaveBeenLastCalledWith(false);

    cleanup();
    expect(markdownListeners.size).toBe(0);
    expect(latexListeners.size).toBe(0);
  });

});
