"use client";

import { createStorage, type Storage } from "unstorage";
import memoryDriver from "unstorage/drivers/memory";
import sessionStorageDriver from "unstorage/drivers/session-storage";
import type { ZodType } from "zod";

import { Result, type Result as ResultT } from "./result";

/**
 * SessionAsyncUtil — 会话级键值存储工具类（基于 unstorage）。
 *
 * 与 `SpAsyncUtil` 的 localStorage 持久化定位不同，本工具只用于当前 tab
 * 会话内的临时 UI 状态，例如跨路由返回时恢复滚动位置。
 */
export class SessionAsyncUtil {
  private static _storage: Storage = createDefaultSessionStorage();

  private constructor() {}

  static setStorage(instance: Storage): void {
    SessionAsyncUtil._storage = instance;
  }

  static getRawStorage(): Storage {
    return SessionAsyncUtil._storage;
  }

  static async getJson<T>(
    key: string,
    schema: ZodType<T>,
  ): Promise<ResultT<T | null>> {
    try {
      const value = await SessionAsyncUtil._storage.getItem<unknown>(key);
      if (value === null || value === undefined) return Result.ok(null);
      const json = typeof value === "string" ? JSON.parse(value) : value;
      return Result.ok(schema.parse(json));
    } catch (e) {
      return Result.err(e);
    }
  }

  static async setJson<T>(
    key: string,
    value: T,
    schema?: ZodType<T>,
  ): Promise<ResultT<void>> {
    try {
      const validated = schema ? schema.parse(value) : value;
      await SessionAsyncUtil._storage.setItem(key, JSON.stringify(validated));
      return Result.ok(undefined);
    } catch (e) {
      return Result.err(e);
    }
  }

  static async remove(key: string): Promise<ResultT<void>> {
    try {
      await SessionAsyncUtil._storage.removeItem(key);
      return Result.ok(undefined);
    } catch (e) {
      return Result.err(e);
    }
  }
}

function createDefaultSessionStorage(): Storage {
  if (typeof window === "undefined") {
    return createStorage({ driver: memoryDriver() });
  }

  try {
    return createStorage({
      driver: sessionStorageDriver({
        base: "cozsweet:",
        storage: window.sessionStorage,
        window,
      }),
    });
  } catch {
    return createStorage({ driver: memoryDriver() });
  }
}
