import { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from 'react';
import type { AuthTokens, PublicUser } from '@/lib/api';
import {
  clearMobileAuth,
  loginWithPassword,
  persistMobileAuth,
  readStoredMobileAuth
} from './mobile-api';

interface MobileAuthContextValue {
  user: PublicUser | null;
  token: string | null;
  sessionId: string | null;
  isAuthenticated: boolean;
  login: (login: string, password: string) => Promise<void>;
  applyAuth: (auth: AuthTokens) => void;
  logout: () => void;
}

const MobileAuthContext = createContext<MobileAuthContextValue | null>(null);

export function MobileAuthProvider({ children }: { children: ReactNode }) {
  const stored = typeof window === 'undefined' ? { token: null, sessionId: null, user: null } : readStoredMobileAuth();
  const [token, setToken] = useState<string | null>(stored.token);
  const [sessionId, setSessionId] = useState<string | null>(stored.sessionId);
  const [user, setUser] = useState<PublicUser | null>(stored.user);

  const applyAuth = useCallback((auth: AuthTokens) => {
    persistMobileAuth(auth);
    setToken(auth.accessToken);
    setSessionId(auth.sessionId);
    setUser(auth.user);
  }, []);

  const login = useCallback(
    async (loginValue: string, password: string) => {
      const auth = await loginWithPassword(loginValue, password);
      if ('requiresTotp' in auth) {
        throw new Error('Для этого аккаунта требуется TOTP-код');
      }
      applyAuth(auth);
    },
    [applyAuth]
  );

  const logout = useCallback(() => {
    clearMobileAuth();
    setToken(null);
    setSessionId(null);
    setUser(null);
  }, []);

  const value = useMemo(
    () => ({
      user,
      token,
      sessionId,
      isAuthenticated: Boolean(user && token),
      login,
      applyAuth,
      logout
    }),
    [applyAuth, login, logout, sessionId, token, user]
  );

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

export function useMobileAuth() {
  const value = useContext(MobileAuthContext);
  if (!value) {
    throw new Error('useMobileAuth должен использоваться внутри MobileAuthProvider');
  }
  return value;
}
