import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react';
import {
  clearAuth,
  ensureSession,
  saveAuth,
  type ShopSessionPayload,
  type StoreSessionStore,
} from '../lib/api';

type StoreSessionContextValue = {
  ready: boolean;
  authenticated: boolean;
  needsSelectStore: boolean;
  store: StoreSessionStore | null;
  applySession: (session: ShopSessionPayload) => void;
  resetSession: () => void;
};

const StoreSessionContext = createContext<StoreSessionContextValue | null>(null);

export function StoreSessionProvider({ children }: { children: ReactNode }) {
  const [ready, setReady] = useState(false);
  const [authenticated, setAuthenticated] = useState(false);
  const [needsSelectStore, setNeedsSelectStore] = useState(false);
  const [store, setStore] = useState<StoreSessionStore | null>(null);

  const applySession = useCallback((session: ShopSessionPayload) => {
    saveAuth(session);
    setAuthenticated(true);
    const nextStore = session.store
      ? {
          ...session.store,
          stores: session.stores ?? session.store.stores,
          isPrimary: session.account?.isPrimary ?? session.store.isPrimary,
        }
      : null;
    setStore(nextStore);
    const storeId = nextStore?.storeId || session.selectedStoreId || '';
    const stores = session.stores ?? nextStore?.stores ?? [];
    setNeedsSelectStore(stores.length > 1 && !storeId);
  }, []);

  const resetSession = useCallback(() => {
    clearAuth();
    setAuthenticated(false);
    setNeedsSelectStore(false);
    setStore(null);
  }, []);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const result = await ensureSession();
        if (cancelled) return;
        setAuthenticated(result.authenticated);
        setStore(result.store);
        setNeedsSelectStore(result.needsSelectStore);
      } catch {
        if (!cancelled) resetSession();
      } finally {
        if (!cancelled) setReady(true);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [resetSession]);

  const value = useMemo(
    () => ({ ready, authenticated, needsSelectStore, store, applySession, resetSession }),
    [ready, authenticated, needsSelectStore, store, applySession, resetSession],
  );

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

export function useStoreSession() {
  const ctx = useContext(StoreSessionContext);
  if (!ctx) throw new Error('useStoreSession must be used within StoreSessionProvider');
  return ctx;
}
