/**
 * User 状态机（XState v5）
 */
import { setup, assign } from "xstate";

import { UserState, initialState } from "./user-state";
import type { UserEvent } from "./user-events";
import {
  userInitActor,
  userFetchActor,
  userLogoutActor,
} from "./user-machine.actors";
import { applyEntitlementSnapshotToView } from "./user-machine.helpers";

// 重新导出 State / Event 类型，保持 machine 文件的公共 API 不变
export type { UserState } from "./user-state";
export { initialState } from "./user-state";
export type { UserEvent } from "./user-events";

// ============================================================
// Machine
// ============================================================
export const userMachine = setup({
  types: {
    context: {} as UserState,
    events: {} as UserEvent,
  },
  actors: {
    userInit: userInitActor,
    userFetch: userFetchActor,
    userLogout: userLogoutActor,
  },
  actions: {
    updateUser: assign(({ event }) => {
      if (event.type !== "UserUpdate") return {};
      return {
        currentUser: event.user,
        isVip: event.user.isVip,
        creditBalance: event.user.creditBalance,
      };
    }),

    clearUser: assign(() => ({
      currentUser: null,
      avatarUrl: null,
      isVip: false,
      creditBalance: 0,
    })),
  },
}).createMachine({
  id: "user",
  initial: "idle",
  context: initialState,
  states: {
    idle: {
      on: {
        UserInit: "initializing",
        UserFetch: "fetching",
        UserUpdate: {
          actions: "updateUser",
        },
        UserClearLocal: {
          actions: "clearUser",
        },
        UserLogout: "loggingOut",
      },
    },

    initializing: {
      invoke: {
        src: "userInit",
        onDone: {
          target: "fetching",
          actions: assign(({ event }) => ({
            currentUser: event.output.user,
            avatarUrl: event.output.avatarUrl,
            isVip: event.output.snapshot?.isVip ?? initialState.isVip,
            creditBalance:
              event.output.snapshot?.creditBalance ??
              initialState.creditBalance,
          })),
        },
        onError: {
          target: "fetching",
        },
      },
    },

    fetching: {
      invoke: {
        src: "userFetch",
        onDone: {
          target: "idle",
          actions: assign(({ context, event }) => {
            const snapshot =
              event.output.snapshot ??
              (context.currentUser
                ? {
                    isVip: context.isVip,
                    creditBalance: context.creditBalance,
                  }
                : null);
            const baseUser = event.output.user ?? context.currentUser;
            return {
              currentUser:
                applyEntitlementSnapshotToView(baseUser, snapshot) ??
                context.currentUser,
              isVip: snapshot?.isVip ?? context.isVip,
              creditBalance: snapshot?.creditBalance ?? context.creditBalance,
              isLoading: false,
            };
          }),
        },
        onError: {
          target: "idle",
          actions: assign({ isLoading: false }),
        },
      },
      entry: assign({ isLoading: true }),
    },

    loggingOut: {
      invoke: {
        src: "userLogout",
        onDone: {
          target: "idle",
          actions: "clearUser",
        },
        onError: {
          target: "idle",
          actions: "clearUser",
        },
      },
    },
  },
});

export type UserMachine = typeof userMachine;
