import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react';
import {
  bootstrapSession,
  clearAuth,
  ensureSession,
  getDeviceKey,
  request,
  saveSession,
  type SessionPayload,
  type UserProfile,
} from '../lib/api';
import { touchPromoIfNeeded } from '../lib/promo';

type UserSessionContextValue = {
  ready: boolean;
  profile: UserProfile | null;
  phoneVerified: boolean;
  applySession: (session: SessionPayload) => void;
  refreshProfile: () => Promise<void>;
  resetSession: () => Promise<void>;
};

const UserSessionContext = createContext<UserSessionContextValue | null>(null);

export function UserSessionProvider({ children }: { children: ReactNode }) {
  const [ready, setReady] = useState(false);
  const [profile, setProfile] = useState<UserProfile | null>(null);
  const [phoneVerified, setPhoneVerified] = useState(false);

  const applySession = useCallback((session: SessionPayload) => {
    saveSession(session);
    if (session.user) setProfile(session.user);
    setPhoneVerified(!!session.phoneVerified || !!session.user?.phoneVerified);
  }, []);

  const refreshProfile = useCallback(async () => {
    const me = await request<UserProfile>('USER_H5', '/auth/me');
    setProfile(me);
    setPhoneVerified(!!me.phoneVerified);
  }, []);

  const resetSession = useCallback(async () => {
    clearAuth();
    const session = await bootstrapSession();
    applySession(session);
  }, [applySession]);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const session = await ensureSession();
        if (cancelled) return;
        applySession(session);
        if (!session.user) {
          await refreshProfile();
        }
        await touchPromoIfNeeded();
      } catch {
        if (!cancelled) {
          try {
            const session = await bootstrapSession();
            applySession(session);
            await refreshProfile();
          } catch {
            /* ignore */
          }
        }
      } finally {
        if (!cancelled) setReady(true);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [applySession, refreshProfile]);

  const value = useMemo(
    () => ({
      ready,
      profile,
      phoneVerified,
      applySession,
      refreshProfile,
      resetSession,
    }),
    [ready, profile, phoneVerified, applySession, refreshProfile, resetSession],
  );

  if (!ready) {
    return (
      <div className="session-boot">
        <p className="session-boot-text">加载中...</p>
      </div>
    );
  }

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

export function useUserSession() {
  const ctx = useContext(UserSessionContext);
  if (!ctx) throw new Error('useUserSession must be used within UserSessionProvider');
  return ctx;
}

export function useOptionalUserSession() {
  return useContext(UserSessionContext);
}

/** @deprecated use profile from useUserSession */
export { getDeviceKey };
