"use client";

/**
 * UserStorage 完整实现（基于 unstorage 抽象）
 *
 * 对齐 Dart 端 `UserStorage`（lib/data/services/storage/user_storage.dart）：
 *   - 三个独立字段：User 对象 / userId / avatarUrl
 *   - `clearUserData()` 批量清空
 *
 * 设计：内部使用 SpAsyncUtil 静态类 + Zod 校验；保持对外 API 完全兼容。
 *
 * 边界：
 *   - `getUser` 走 `UserSchema` 解析：缺字段时 Zod `.default()` 自动兜底
 *   - `setUser` 走 `UserSchema` 校验写入：保证存储的总是完整 UserData
 *   - 单例挂在 class 静态字段，HMR 复用安全
 */

import {
  UserEntitlementSnapshotSchema,
  type UserEntitlementSnapshotData,
} from "@/data/schemas/user/user_entitlement_snapshot";
import { UserSchema, type UserData } from "@/data/schemas/user/user";
import { type Result as ResultT, SpAsyncUtil } from "@/utils";
import { StorageKeys } from "../storage_keys";
import type { IUserStorage } from "./iuser_storage";

export class UserStorage implements IUserStorage {
  private static _instance: UserStorage | null = null;

  static getInstance(): UserStorage {
    if (!UserStorage._instance) UserStorage._instance = new UserStorage();
    return UserStorage._instance;
  }

  /** @internal */
  static _resetForTests(): void {
    UserStorage._instance = null;
  }

  // ---- user object ----

  getUser(): Promise<ResultT<UserData | null>> {
    return SpAsyncUtil.getJson(StorageKeys.user, UserSchema);
  }

  setUser(user: UserData): Promise<ResultT<void>> {
    return SpAsyncUtil.setJson(StorageKeys.user, user, UserSchema);
  }

  clearUser(): Promise<ResultT<void>> {
    return SpAsyncUtil.remove(StorageKeys.user);
  }

  // ---- userId ----

  getUserId(): Promise<ResultT<string | null>> {
    return SpAsyncUtil.getString(StorageKeys.userId);
  }

  setUserId(id: string): Promise<ResultT<void>> {
    return SpAsyncUtil.setString(StorageKeys.userId, id);
  }

  clearUserId(): Promise<ResultT<void>> {
    return SpAsyncUtil.remove(StorageKeys.userId);
  }

  // ---- avatarUrl ----

  getAvatarUrl(): Promise<ResultT<string | null>> {
    return SpAsyncUtil.getString(StorageKeys.userAvatar);
  }

  setAvatarUrl(url: string): Promise<ResultT<void>> {
    return SpAsyncUtil.setString(StorageKeys.userAvatar, url);
  }

  clearAvatarUrl(): Promise<ResultT<void>> {
    return SpAsyncUtil.remove(StorageKeys.userAvatar);
  }

  // ---- entitlement snapshot ----

  getEntitlementSnapshot(): Promise<
    ResultT<UserEntitlementSnapshotData | null>
  > {
    return SpAsyncUtil.getJson(
      StorageKeys.userEntitlementSnapshot,
      UserEntitlementSnapshotSchema,
    );
  }

  setEntitlementSnapshot(
    data: UserEntitlementSnapshotData,
  ): Promise<ResultT<void>> {
    return SpAsyncUtil.setJson(
      StorageKeys.userEntitlementSnapshot,
      data,
      UserEntitlementSnapshotSchema,
    );
  }

  clearEntitlementSnapshot(): Promise<ResultT<void>> {
    return SpAsyncUtil.remove(StorageKeys.userEntitlementSnapshot);
  }

  // ---- bulk clear ----

  async clearUserData(): Promise<ResultT<void>> {
    const r1 = await this.clearUser();
    if (!r1.success) return r1;
    const r2 = await this.clearUserId();
    if (!r2.success) return r2;
    const r3 = await this.clearAvatarUrl();
    if (!r3.success) return r3;
    return this.clearEntitlementSnapshot();
  }
}
