/**
 * `localStorage`-backed {@link UiPreferencesGateway} (ticket #29).
 *
 * The only place that touches `window.localStorage`; features go through the
 * port via DI. Everything is best-effort: a missing / private-mode / quota-full
 * storage, or a corrupt JSON entry, degrades silently to "no preference" rather
 * than throwing into the UI (persisted UI filters must never break the app).
 */

import type { UiPreferencesGateway } from "@/ports";

/** Returns the `Storage` if usable in this environment, else `null`. */
function storage(): Storage | null {
  try {
    return typeof window !== "undefined" ? window.localStorage : null;
  } catch {
    // Accessing `localStorage` can throw (sandboxed / disabled cookies).
    return null;
  }
}

export class LocalStorageUiPreferencesGateway implements UiPreferencesGateway {
  read(key: string): unknown {
    const store = storage();
    if (!store) return null;
    let raw: string | null;
    try {
      raw = store.getItem(key);
    } catch {
      return null;
    }
    if (raw === null) return null;
    try {
      return JSON.parse(raw);
    } catch {
      // Corrupt entry — drop it so we stop tripping over it, return default.
      try {
        store.removeItem(key);
      } catch {
        /* ignore */
      }
      return null;
    }
  }

  write(key: string, value: unknown): void {
    const store = storage();
    if (!store) return;
    try {
      store.setItem(key, JSON.stringify(value));
    } catch {
      /* quota / serialisation failure — persistence is best-effort */
    }
  }

  remove(key: string): void {
    const store = storage();
    if (!store) return;
    try {
      store.removeItem(key);
    } catch {
      /* ignore */
    }
  }
}
