"use client";
/**
 * AuthContext：基于 XState actor context 和 selector 的 React Provider。
 */
import type { Dispatch, ReactNode } from "react";
import { createActorContext, shallowEqual } from "@xstate/react";
import type { SnapshotFrom } from "xstate";

import { useHasHydrated } from "@/hooks/use-has-hydrated";

import { authMachine, initialState } from "./auth-machine";
import type { AuthEvent, AuthState as MachineContext } from "./auth-machine";

/**
 * 对外暴露的 State 形状
 */
interface AuthState {
  authPanelMode: MachineContext["authPanelMode"];
  isLoading: boolean;
  errorMessage: string | null;
  /** 当前登录状态（未登录 / 游客 / OAuth / 邮箱） */
  loginStatus: MachineContext["loginStatus"];
  /** 启动时的本地登录态恢复是否已经完成 */
  hasInitialized: MachineContext["hasInitialized"];
}

type AuthSnapshot = SnapshotFrom<typeof authMachine>;
type AuthSelector<T> = (snapshot: AuthSnapshot) => T;

const AuthActorContext = createActorContext(authMachine);
const hydrationAuthState: AuthState = {
  authPanelMode: initialState.authPanelMode,
  isLoading: false,
  errorMessage: initialState.errorMessage,
  loginStatus: initialState.loginStatus,
  hasInitialized: initialState.hasInitialized,
};

export interface AuthProviderProps {
  children: ReactNode;
}

export function AuthProvider({ children }: AuthProviderProps) {
  return <AuthActorContext.Provider>{children}</AuthActorContext.Provider>;
}

export function useAuthState(): AuthState {
  const state = useAuthSelector(selectAuthState, shallowEqual);
  const hasHydrated = useHasHydrated();
  return hasHydrated ? state : hydrationAuthState;
}

export function useAuthDispatch(): Dispatch<AuthEvent> {
  return AuthActorContext.useActorRef().send;
}

export function useAuthSelector<T>(
  selector: AuthSelector<T>,
  compare?: (previous: T, next: T) => boolean,
): T {
  return AuthActorContext.useSelector(selector, compare);
}

function selectAuthState(state: AuthSnapshot): AuthState {
  return {
    authPanelMode: state.context.authPanelMode,
    isLoading: selectAuthIsLoading(state),
    errorMessage: state.context.errorMessage,
    loginStatus: state.context.loginStatus,
    hasInitialized: state.context.hasInitialized,
  };
}

export function selectAuthIsLoading(state: AuthSnapshot): boolean {
  return (
    state.matches("loadingEmailLogin") ||
    state.matches("loadingEmailRegister") ||
    state.matches("loadingOAuth") ||
    state.matches("initializing") ||
    state.matches("loggingOut") ||
    state.matches("syncingGoogleBackend") ||
    state.matches("syncingFacebookBackend") ||
    state.matches("loadingGuestLogin")
  );
}
