import type { ZodSchema } from "zod";

const PREFIX = "afl_";

function prefixed(key: string): string {
  return `${PREFIX}${key}`;
}

export const storage = {
  get<T>(key: string, schema: ZodSchema<T>): T | null {
    try {
      const raw = localStorage.getItem(prefixed(key));
      if (raw === null) return null;
      const parsed: unknown = JSON.parse(raw);
      const result = schema.safeParse(parsed);
      return result.success ? result.data : null;
    } catch {
      return null;
    }
  },

  set<T>(key: string, value: T, schema: ZodSchema<T>): void {
    schema.parse(value);
    localStorage.setItem(prefixed(key), JSON.stringify(value));
  },

  delete(key: string): void {
    localStorage.removeItem(prefixed(key));
  },

  clear(): void {
    const keysToRemove: string[] = [];
    for (let i = 0; i < localStorage.length; i++) {
      const k = localStorage.key(i);
      if (k?.startsWith(PREFIX)) {
        keysToRemove.push(k);
      }
    }
    for (const k of keysToRemove) {
      localStorage.removeItem(k);
    }
  },
};

/**
 * Thin wrapper over `sessionStorage` for same-tab ephemeral state —
 * cross-page prefill handoff, non-persistent UI flags, etc. No schema
 * validation; callers own their key namespace (e.g. `afl-prefill:*`)
 * and serialize/deserialize JSON themselves. All operations no-op
 * when `sessionStorage` is undefined (SSR-safe).
 *
 * Exists so the rest of the codebase can stay under the
 * `no-restricted-globals` rule that blocks direct sessionStorage access.
 */

const SESSION_PREFIX = "afl_";

export const sessionStore = {
  getRaw(key: string): string | null {
    if (typeof sessionStorage === "undefined") return null;
    try {
      return sessionStorage.getItem(key);
    } catch {
      return null;
    }
  },

  setRaw(key: string, value: string): void {
    if (typeof sessionStorage === "undefined") return;
    try {
      sessionStorage.setItem(key, value);
    } catch {
      // ignore quota/disabled
    }
  },

  delete(key: string): void {
    if (typeof sessionStorage === "undefined") return;
    try {
      sessionStorage.removeItem(key);
    } catch {
      // ignore disabled
    }
  },

  clear(): void {
    if (typeof sessionStorage === "undefined") return;
    try {
      sessionStorage.clear();
    } catch {
      // ignore disabled
    }
  },

  /** Schema-validated get from sessionStorage under the `afl_` namespace. */
  get<T>(key: string, schema: ZodSchema<T>): T | null {
    try {
      const raw = this.getRaw(SESSION_PREFIX + key);
      if (raw === null) return null;
      const parsed: unknown = JSON.parse(raw);
      const result = schema.safeParse(parsed);
      return result.success ? result.data : null;
    } catch {
      return null;
    }
  },

  /** Schema-validated set into sessionStorage under the `afl_` namespace. */
  set<T>(key: string, value: T, schema: ZodSchema<T>): void {
    schema.parse(value);
    this.setRaw(SESSION_PREFIX + key, JSON.stringify(value));
  },

  /** Delete a key from the `afl_` namespace in sessionStorage. */
  deleteNs(key: string): void {
    this.delete(SESSION_PREFIX + key);
  },
};
