import { afterEach, describe, expect, test, vi } from 'vitest';
import { requestPersistentStorage } from './storage-persist';

const realNavigator = globalThis.navigator;

/** Swap `navigator` for one exposing the given `storage` (or none). */
function withStorage(storage: unknown) {
  Object.defineProperty(globalThis, 'navigator', {
    value: storage === undefined ? {} : { storage },
    configurable: true,
  });
}

afterEach(() => {
  Object.defineProperty(globalThis, 'navigator', { value: realNavigator, configurable: true });
  vi.restoreAllMocks();
});

describe('requestPersistentStorage', () => {
  test('reports unsupported when the StorageManager API is absent', async () => {
    withStorage(undefined);
    expect(await requestPersistentStorage()).toEqual({ supported: false });
  });

  test('reports unsupported when persist/persisted are missing', async () => {
    withStorage({ estimate: () => Promise.resolve({}) });
    expect(await requestPersistentStorage()).toEqual({ supported: false });
  });

  test('does not re-request when already persisted', async () => {
    const persist = vi.fn();
    withStorage({ persisted: vi.fn().mockResolvedValue(true), persist });
    expect(await requestPersistentStorage()).toEqual({
      supported: true,
      persisted: true,
      alreadyPersisted: true,
    });
    expect(persist).not.toHaveBeenCalled();
  });

  test('requests persistence once and reports granted', async () => {
    const persist = vi.fn().mockResolvedValue(true);
    withStorage({ persisted: vi.fn().mockResolvedValue(false), persist });
    expect(await requestPersistentStorage()).toEqual({
      supported: true,
      persisted: true,
      alreadyPersisted: false,
    });
    expect(persist).toHaveBeenCalledTimes(1);
  });

  test('reports not granted when the request is denied', async () => {
    withStorage({
      persisted: vi.fn().mockResolvedValue(false),
      persist: vi.fn().mockResolvedValue(false),
    });
    expect(await requestPersistentStorage()).toEqual({
      supported: true,
      persisted: false,
      alreadyPersisted: false,
    });
  });

  test('never rejects — a thrown request resolves to not-persisted', async () => {
    withStorage({
      persisted: vi.fn().mockRejectedValue(new Error('blocked')),
      persist: vi.fn(),
    });
    expect(await requestPersistentStorage()).toEqual({
      supported: true,
      persisted: false,
      alreadyPersisted: false,
    });
  });
});
