/**
 * Storage Adapters
 *
 * @module @bytelyst/sync/storage
 */

import type { StorageAdapter } from './types.js';

// ─────────────────────────────────────────────────────────────────────────────
// LocalStorage Adapter (Web)
// ─────────────────────────────────────────────────────────────────────────────

export class LocalStorageAdapter implements StorageAdapter {
  private prefix: string;

  constructor(prefix = 'bytelyst:sync:') {
    this.prefix = prefix;
  }

  getItem<T>(key: string): T | null {
    if (typeof localStorage === 'undefined') return null;
    const value = localStorage.getItem(this.prefix + key);
    if (!value) return null;
    try {
      return JSON.parse(value) as T;
    } catch {
      return null;
    }
  }

  setItem<T>(key: string, value: T): void {
    if (typeof localStorage === 'undefined') return;
    localStorage.setItem(this.prefix + key, JSON.stringify(value));
  }

  removeItem(key: string): void {
    if (typeof localStorage === 'undefined') return;
    localStorage.removeItem(this.prefix + key);
  }

  keys(): string[] {
    if (typeof localStorage === 'undefined') return [];
    const keys: string[] = [];
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i);
      if (key && key.startsWith(this.prefix)) {
        keys.push(key.slice(this.prefix.length));
      }
    }
    return keys;
  }
}

// ─────────────────────────────────────────────────────────────────────────────
// In-Memory Adapter (Testing / SSR)
// ─────────────────────────────────────────────────────────────────────────────

export class InMemoryAdapter implements StorageAdapter {
  private store = new Map<string, unknown>();

  getItem<T>(key: string): T | null {
    const value = this.store.get(key);
    return value !== undefined ? (value as T) : null;
  }

  setItem<T>(key: string, value: T): void {
    this.store.set(key, value);
  }

  removeItem(key: string): void {
    this.store.delete(key);
  }

  keys(): string[] {
    return Array.from(this.store.keys());
  }

  clear(): void {
    this.store.clear();
  }
}

// ─────────────────────────────────────────────────────────────────────────────
// MMKV Adapter Interface (React Native)
// ─────────────────────────────────────────────────────────────────────────────

export interface MMKVInstance {
  getString(key: string): string | undefined;
  set(key: string, value: string): void;
  delete(key: string): void;
  getAllKeys(): string[];
}

export class MMKVAdapter implements StorageAdapter {
  private mmkv: MMKVInstance;
  private prefix: string;

  constructor(mmkv: MMKVInstance, prefix = 'sync:') {
    this.mmkv = mmkv;
    this.prefix = prefix;
  }

  getItem<T>(key: string): T | null {
    const value = this.mmkv.getString(this.prefix + key);
    if (!value) return null;
    try {
      return JSON.parse(value) as T;
    } catch {
      return null;
    }
  }

  setItem<T>(key: string, value: T): void {
    this.mmkv.set(this.prefix + key, JSON.stringify(value));
  }

  removeItem(key: string): void {
    this.mmkv.delete(this.prefix + key);
  }

  keys(): string[] {
    return this.mmkv
      .getAllKeys()
      .filter(k => k.startsWith(this.prefix))
      .map(k => k.slice(this.prefix.length));
  }
}
