import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
import { changeExternalPassword, getExternalSession, loginExternal, logoutExternal } from "../api/auth.js";
import { ExternalApiError, setExternalUnauthorizedHandler } from "../api/client.js";

const ExternalAuthContext = createContext(null);

export function ExternalAuthProvider({ children }) {
  const [session, setSession] = useState(null);
  const [initializing, setInitializing] = useState(true);
  const [initializationError, setInitializationError] = useState("");

  const refresh = useCallback(async () => {
    setInitializationError("");
    try {
      const nextSession = await getExternalSession();
      setSession(nextSession);
      return nextSession;
    } catch (error) {
      setSession(null);
      if (!(error instanceof ExternalApiError && error.status === 401)) {
        setInitializationError(error.message || "会话校验失败");
      }
      return null;
    } finally {
      setInitializing(false);
    }
  }, []);

  useEffect(() => {
    refresh();
  }, [refresh]);

  useEffect(() => {
    // Any protected request returning 401 invalidates the entire external session; it never mutates the main-admin session.
    return setExternalUnauthorizedHandler(() => setSession(null));
  }, []);

  const login = useCallback(async (credentials) => {
    const nextSession = await loginExternal(credentials);
    setSession(nextSession);
    return nextSession;
  }, []);

  const logout = useCallback(async () => {
    try {
      await logoutExternal();
    } finally {
      setSession(null);
    }
  }, []);

  const changePassword = useCallback(async (payload) => {
    const responseSession = await changeExternalPassword(payload);
    const nextSession = responseSession?.appCode ? responseSession : await getExternalSession();
    setSession({ ...nextSession, passwordChangeRequired: false });
    return nextSession;
  }, []);

  const value = useMemo(
    () => ({ changePassword, initializationError, initializing, login, logout, refresh, session }),
    [changePassword, initializationError, initializing, login, logout, refresh, session]
  );

  return <ExternalAuthContext.Provider value={value}>{children}</ExternalAuthContext.Provider>;
}

export function useExternalAuth() {
  const context = useContext(ExternalAuthContext);
  if (!context) {
    throw new Error("useExternalAuth must be used inside ExternalAuthProvider");
  }
  return context;
}
