import { fromPromise } from "xstate";

import { getUserRepository } from "@/data/repositories/user_repository";
import type {
  UserEntitlementsData,
  UserEntitlementSnapshotData,
} from "@/data/schemas/user";
import { UserStorage } from "@/data/storage/user/user_storage";
import type { UserView } from "@/stores/user/user-view";
import { Result } from "@/utils/result";

import {
  applyEntitlementSnapshotToView,
  toEntitlementSnapshot,
  toView,
} from "../../helper/view";

export interface UserFetchData {
  user: UserView | null;
  snapshot: UserEntitlementSnapshotData | null;
  entitlements?: UserEntitlementsData | null;
}

export const userFetchActor = fromPromise<UserFetchData>(async () => {
  const userRepo = getUserRepository();
  const userStorage = UserStorage.getInstance();
  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;
  const entitlements = Result.isOk(entitlementsResult)
    ? entitlementsResult.data
    : null;
  if (snapshot) await userStorage.setEntitlementSnapshot(snapshot);

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

  const view = applyEntitlementSnapshotToView(
    toView(userResult.data),
    snapshot,
  );
  await userStorage.setUser(userResult.data);
  return { user: view, snapshot, entitlements };
});
