import type { DoneActorEvent, ErrorActorEvent } from "xstate";

import type { LoginStatus } from "@/data/dto/auth";
import type { AuthProvider } from "@/lib/auth/auth_platform";

import { toAuthErrorMessage } from "../helper/error";
import { credentialsMachineSetup } from "./credentials-flow";
import { createAuthActorActionSetup } from "./setup";

export const oauthMachineSetup = credentialsMachineSetup;

const oauthSyncDoneSetup =
  createAuthActorActionSetup<DoneActorEvent<LoginStatus>>();
const oauthErrorSetup = createAuthActorActionSetup<ErrorActorEvent>();

const applyOAuthSyncSuccessAction = oauthSyncDoneSetup.assign(({ event }) => ({
  loginStatus: event.output,
  errorMessage: null,
  hasInitialized: true,
}));

const applyOAuthSyncErrorAction = oauthErrorSetup.assign(({ event }) => ({
  errorMessage: toAuthErrorMessage(event.error),
  hasInitialized: true,
}));

const applyOAuthLaunchErrorAction = oauthErrorSetup.assign(({ event }) => ({
  errorMessage: toAuthErrorMessage(event.error),
}));

export const loadingOAuthState = oauthMachineSetup.createStateConfig({
  entry: "clearAuthError",
  invoke: {
    src: "oauthSignIn",
    input: ({ event }) => {
      if (event.type === "AuthGoogleLoginSubmitted") return event.provider;
      if (event.type === "AuthFacebookLoginSubmitted") return event.provider;
      return "google" as AuthProvider;
    },
    onDone: { target: "idle" },
    onError: {
      target: "idle",
      actions: applyOAuthLaunchErrorAction,
    },
  },
});

export const syncingGoogleBackendState = oauthMachineSetup.createStateConfig({
  entry: "clearAuthError",
  invoke: {
    src: "syncGoogleBackend",
    input: ({ event }) => ({
      idToken: event.type === "AuthGoogleSyncSubmitted" ? event.idToken : "",
    }),
    onDone: {
      target: "idle",
      actions: applyOAuthSyncSuccessAction,
    },
    onError: {
      target: "idle",
      actions: applyOAuthSyncErrorAction,
    },
  },
});

export const syncingFacebookBackendState = oauthMachineSetup.createStateConfig({
  entry: "clearAuthError",
  invoke: {
    src: "syncFacebookBackend",
    input: ({ event }) => ({
      accessToken:
        event.type === "AuthFacebookSyncSubmitted" ? event.accessToken : "",
    }),
    onDone: {
      target: "idle",
      actions: applyOAuthSyncSuccessAction,
    },
    onError: {
      target: "idle",
      actions: applyOAuthSyncErrorAction,
    },
  },
});
