import { describe, it, expect, beforeEach } from 'vitest';
import 'fake-indexeddb/auto';
import { SecureStorage } from './secure-storage.js';

describe('SecureStorage', () => {
  let storage: SecureStorage;

  beforeEach(async () => {
    storage = new SecureStorage('com.test.app');
    await storage.clear();
  });

  // ── Basic CRUD ──────────────────────────────────

  it('set and get', async () => {
    await storage.set('token', 'abc123');
    const val = await storage.get('token');
    expect(val).toBe('abc123');
  });

  it('get returns null for missing key', async () => {
    const val = await storage.get('nonexistent');
    expect(val).toBeNull();
  });

  it('overwrite existing key', async () => {
    await storage.set('token', 'first');
    await storage.set('token', 'second');
    const val = await storage.get('token');
    expect(val).toBe('second');
  });

  it('delete removes value', async () => {
    await storage.set('token', 'abc');
    await storage.delete('token');
    const val = await storage.get('token');
    expect(val).toBeNull();
  });

  it('delete non-existent key does not throw', async () => {
    await expect(storage.delete('nope')).resolves.toBeUndefined();
  });

  // ── Clear ───────────────────────────────────────

  it('clear removes all values', async () => {
    await storage.set('a', '1');
    await storage.set('b', '2');
    await storage.clear();
    expect(await storage.get('a')).toBeNull();
    expect(await storage.get('b')).toBeNull();
  });

  // ── Has ─────────────────────────────────────────

  it('has returns true for existing key', async () => {
    await storage.set('x', 'val');
    expect(await storage.has('x')).toBe(true);
  });

  it('has returns false for missing key', async () => {
    expect(await storage.has('missing')).toBe(false);
  });

  // ── Keys ────────────────────────────────────────

  it('keys lists stored keys', async () => {
    await storage.set('alpha', '1');
    await storage.set('beta', '2');
    const keys = await storage.keys();
    expect(keys.sort()).toEqual(['alpha', 'beta']);
  });

  it('keys returns empty for fresh storage', async () => {
    const keys = await storage.keys();
    expect(keys).toEqual([]);
  });

  // ── Namespace isolation ─────────────────────────

  it('different namespaces are isolated', async () => {
    const s1 = new SecureStorage('ns1');
    const s2 = new SecureStorage('ns2');
    await s1.set('key', 'from-s1');
    await s2.set('key', 'from-s2');
    expect(await s1.get('key')).toBe('from-s1');
    expect(await s2.get('key')).toBe('from-s2');
  });

  // ── Data types ──────────────────────────────────

  it('empty string', async () => {
    await storage.set('empty', '');
    const val = await storage.get('empty');
    expect(val).toBe('');
  });

  it('unicode values', async () => {
    const text = 'こんにちは世界 🌍 مرحبا Ñoño';
    await storage.set('unicode', text);
    expect(await storage.get('unicode')).toBe(text);
  });

  it('large value', async () => {
    const big = 'X'.repeat(100_000);
    await storage.set('big', big);
    expect(await storage.get('big')).toBe(big);
  });

  it('JSON string value', async () => {
    const json = JSON.stringify({ token: 'abc', user: { id: 1 } });
    await storage.set('session', json);
    const parsed = JSON.parse((await storage.get('session'))!);
    expect(parsed.token).toBe('abc');
    expect(parsed.user.id).toBe(1);
  });

  // ── isSupported ─────────────────────────────────

  it('isSupported returns true in test environment', () => {
    expect(SecureStorage.isSupported()).toBe(true);
  });
});
