/** Exception-contained persistence over a caller-owned local storage adapter. */
import { decodeLocalProfile, encodeLocalProfile, type LocalProfile } from "./model.ts";

export interface ProfileStorageAdapter {
  getItem(key: string): string | null;
  setItem(key: string, value: string): void;
  removeItem(key: string): void;
}

export type ProfileSaveResult = { ok: true } | { ok: false; error: string };
export type ProfileClearResult = ProfileSaveResult;
export type ProfileLoadResult =
  | { status: "loaded"; profile: LocalProfile; migrated: boolean }
  | { status: "missing" }
  | { status: "invalid"; error: string }
  | { status: "unavailable"; error: string };

function validKey(key: string): boolean {
  return typeof key === "string" && key.trim().length > 0;
}

export function saveLocalProfile(
  storage: ProfileStorageAdapter,
  key: string,
  profile: LocalProfile,
): ProfileSaveResult {
  if (!validKey(key)) return { ok: false, error: "profile: storage key is empty" };
  let encoded: string;
  try {
    encoded = encodeLocalProfile(profile);
  } catch (error) {
    return { ok: false, error: error instanceof Error ? error.message : "profile: encoding failed" };
  }
  try {
    storage.setItem(key, encoded);
    return { ok: true };
  } catch {
    return { ok: false, error: "profile: storage is unavailable" };
  }
}

export function loadLocalProfile(storage: ProfileStorageAdapter, key: string): ProfileLoadResult {
  if (!validKey(key)) return { status: "invalid", error: "profile: storage key is empty" };
  let encoded: string | null;
  try {
    encoded = storage.getItem(key);
  } catch {
    return { status: "unavailable", error: "profile: storage is unavailable" };
  }
  if (encoded === null) return { status: "missing" };
  const decoded = decodeLocalProfile(encoded);
  if (!decoded.ok) return { status: "invalid", error: decoded.error };
  return { status: "loaded", profile: decoded.profile, migrated: decoded.migrated };
}

export function clearLocalProfile(storage: ProfileStorageAdapter, key: string): ProfileClearResult {
  if (!validKey(key)) return { ok: false, error: "profile: storage key is empty" };
  try {
    storage.removeItem(key);
    return { ok: true };
  } catch {
    return { ok: false, error: "profile: storage is unavailable" };
  }
}
