"use client";
/**
 * AuthContext：基于 XState v5 的 React Context Provider
 *
 * 业务事件（`Auth*Submitted`）通过 `useMachine(authMachine).send()` 派发。
 * XState 自动处理异步副作用（invoke + fromPromise actors）。
 *
 * 兼容性：保持原 `useAuthState()` / `useAuthDispatch()` API，
 * 内部将 XState 状态机快照映射回原 `AuthState` 形状。
 */
import {
  type Dispatch,
  type ReactNode,
  createContext,
  useContext,
  useMemo,
} from "react";
import { useMachine } from "@xstate/react";

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

/**
 * 对外暴露的 State 形状（保持与原 AuthState 兼容）
 */
interface AuthState {
  authPanelMode: MachineContext["authPanelMode"];
  authMode: MachineContext["authMode"];
  email: string;
  password: string;
  username: string;
  confirmPassword: string;
  isLoading: boolean;
  errorMessage: string | null;
  isSuccess: boolean;
  loginType: MachineContext["loginType"];
}

const AuthStateCtx = createContext<AuthState | null>(null);
const AuthDispatchCtx = createContext<Dispatch<AuthEvent> | null>(null);

export interface AuthProviderProps {
  children: ReactNode;
}

export function AuthProvider({ children }: AuthProviderProps) {
  const [state, send] = useMachine(authMachine);

  // 映射 XState 状态机快照 → 原 AuthState 形状
  const authState = useMemo<AuthState>(
    () => ({
      authPanelMode: state.context.authPanelMode,
      authMode: state.context.authMode,
      email: state.context.email,
      password: state.context.password,
      username: state.context.username,
      confirmPassword: state.context.confirmPassword,
      // isLoading 仅来自邮箱登录 actor（社交登录改由 NextAuth 处理，UI 自行管 busy 状态）
      isLoading: state.matches("loadingEmailLogin") ||
        state.matches("loadingEmailRegister"),
      errorMessage: state.context.errorMessage,
      isSuccess: state.matches("success"),
      loginType: state.context.loginType,
    }),
    [state],
  );

  return (
    <AuthStateCtx.Provider value={authState}>
      <AuthDispatchCtx.Provider value={send}>{children}</AuthDispatchCtx.Provider>
    </AuthStateCtx.Provider>
  );
}

export function useAuthState(): AuthState {
  const ctx = useContext(AuthStateCtx);
  if (!ctx) throw new Error("useAuthState must be used inside <AuthProvider>");
  return ctx;
}

export function useAuthDispatch(): Dispatch<AuthEvent> {
  const ctx = useContext(AuthDispatchCtx);
  if (!ctx)
    throw new Error("useAuthDispatch must be used inside <AuthProvider>");
  return ctx;
}
