import { describe, expect, it } from 'vitest';
import { StorageQuotaError } from '../infrastructure/db';
import { entityStorageErrorNotification, storageErrorNotification } from './storage-errors';

describe('storageErrorNotification', () => {
  describe('a failure the user can fix (storage full)', () => {
    it('tells them the step to take and carries no diagnostic detail', () => {
      const n = storageErrorNotification('save', new StorageQuotaError());
      expect(n.kind).toBe('error');
      expect(n.title).toBe('Storage full');
      expect(n.message.toLowerCase()).toContain('delete');
      // Nothing to report — the fix is in the user's hands.
      expect(n.detail).toBeUndefined();
    });
  });

  describe('a failure the user cannot fix', () => {
    it('explains a load failure and attaches a reportable diagnostic', () => {
      const n = storageErrorNotification('load', new DOMException('blocked', 'SecurityError'));
      expect(n.kind).toBe('error');
      expect(n.title).toBe("Couldn't open your library");
      expect(n.detail).toBeDefined();
      // The diagnostic names the operation and the underlying error.
      expect(n.detail).toContain('load');
      expect(n.detail).toContain('SecurityError');
      expect(n.detail).toContain('blocked');
    });

    it('uses the right title for a failed save vs delete and includes detail', () => {
      const save = storageErrorNotification('save', new Error('boom'));
      expect(save.title).toBe("Couldn't save your changes");
      expect(save.detail).toContain('save failed');
      expect(save.detail).toContain('boom');

      const del = storageErrorNotification('delete', new Error('boom'));
      expect(del.title).toBe("Couldn't delete the snippet");
      expect(del.detail).toContain('delete failed');
    });

    it('describes a non-Error throw without crashing', () => {
      const n = storageErrorNotification('save', 'weird string');
      expect(n.detail).toContain('weird string');
    });
  });
});

describe('entityStorageErrorNotification', () => {
  it('names the entity in the title, message, and diagnostic', () => {
    const save = entityStorageErrorNotification('dataset', 'save', new Error('boom'));
    expect(save.kind).toBe('error');
    expect(save.title).toBe("Couldn't save the dataset");
    expect(save.message).toContain('dataset change');
    expect(save.detail).toBe('Dataset save failed: Error: boom'); // capitalized noun in trace

    const del = entityStorageErrorNotification('font', 'delete', new Error('boom'));
    expect(del.title).toBe("Couldn't delete the font");
    expect(del.detail).toContain('Font delete failed');
  });

  it('detects a quota failure for any entity tier (not just snippets)', () => {
    const n = entityStorageErrorNotification('dataset', 'save', new StorageQuotaError());
    expect(n.title).toBe('Storage full');
    expect(n.message.toLowerCase()).toContain('dataset');
    expect(n.message.toLowerCase()).toContain('delete');
    expect(n.detail).toBeUndefined(); // nothing to report — the fix is in the message
  });

  it('frames a load failure with the entity noun, not "snippets"', () => {
    const n = entityStorageErrorNotification(
      'dataset',
      'load',
      new DOMException('blocked', 'SecurityError'),
    );
    expect(n.title).toBe("Couldn't open your datasets");
    expect(n.message).toContain('datasets');
    expect(n.message).not.toContain('snippet');
    expect(n.detail).toContain('load');
    expect(n.detail).toContain('SecurityError');
  });

  it('describes a non-Error throw without crashing', () => {
    const n = entityStorageErrorNotification('theme', 'save', 'weird string');
    expect(n.detail).toBe('weird string');
  });
});
