/**
 * User 状态机：Actors（异步服务）
 *
 * 从 `user-machine.ts` 抽出的"Actors"段：
 *   - `userInitActor`（fromPromise：读 UserStorage 并行 user + avatarUrl）
 *   - `userFetchActor`（fromPromise：调 API + 持久化到本地）
 *   - `userLogoutActor`（fromPromise：auth logout + 清本地数据）
 *
 * 设计：
 *   - 依赖 `user-machine.helpers.ts`（toView, readInitData, userStorage）
 *   - 仓库使用懒单例 getter，actor 执行时才创建实例
 *   - 命名约定：`[user-machine]` 前缀日志（如未来加）—— 与 chat 模块对齐
 */

import { fromPromise } from "xstate";

import { getUserRepository } from "@/data/repositories/user_repository";
import { getAuthRepository } from "@/data/repositories/auth_repository";
import { Result } from "@/utils";

import {
  applyEntitlementSnapshotToView,
  type InitData,
  readInitData,
  toEntitlementSnapshot,
  toView,
  type UserFetchData,
  userStorage,
} from "./user-machine.helpers";

// ============================================================
// Init actor：从 UserStorage 读 user + avatarUrl
// ============================================================
/**
 * 读本地 user + avatarUrl（并行）。
 * - 失败/无数据 → 返回 null，不抛错（machine 走 onDone 回到 idle，context 是 null）
 * - onDone 赋 currentUser + avatarUrl 到 context
 */
export const userInitActor = fromPromise<InitData>(async () => readInitData());

// ============================================================
// Fetch actor：调 API 拉当前用户 + 持久化
// ============================================================
/**
 * 调 `userRepo.getCurrentUser + getEntitlements` 拉当前 user 与权益：
 * - user 成功 → 转 UserView + 写本地（userStorage.setUser）
 * - entitlements 成功 → 提取 isVip/creditBalance 写本地轻量快照
 * - 任一失败都不阻断另一方，machine 层负责保留已有 context
 */
export const userFetchActor = fromPromise<UserFetchData>(async () => {
  const userRepo = getUserRepository();
  const [userResult, entitlementsResult] = await Promise.all([
    userRepo.getCurrentUser(),
    userRepo.getEntitlements(),
  ]);

  const snapshot = Result.isOk(entitlementsResult)
    ? toEntitlementSnapshot({
        isVip: entitlementsResult.data.isVip,
        creditBalance: entitlementsResult.data.creditBalance,
      })
    : null;
  if (snapshot) {
    await userStorage.setEntitlementSnapshot(snapshot);
  }

  if (Result.isErr(userResult)) {
    return { user: null, snapshot };
  }

  const view = applyEntitlementSnapshotToView(
    toView(userResult.data.toJson()),
    snapshot,
  );
  // 持久化到本地
  await userStorage.setUser(userResult.data.toJson());
  return { user: view, snapshot };
});

// ============================================================
// Logout actor：后端登出 + 清本地用户数据
// ============================================================
/**
 * 登出：
 * - 调 `authRepo.logout` 让后端吊销 token
 * - `userStorage.clearUserData` 清本地 user / avatar 等
 * - onDone / onError 都跑 `clearUser` action（machine 层）—— 失败也清本地
 */
export const userLogoutActor = fromPromise<void>(async () => {
  await getAuthRepository().logout();
});
