/**
 * Authentication utilities for managing access tokens across multiple accounts
 */

import { MatrixClient } from 'matrix-js-sdk';
import { getLocalStorageItem, setLocalStorageItem } from '../state/utils/atomWithLocalStorage';
import { Session, Sessions, MATRIX_SESSIONS_KEY, CURRENT_SESSION_KEY } from '../state/sessions';

/**
 * Global reference to the current MatrixClient instance
 * Set by initMatrix.ts when a client is created
 */
let globalMatrixClient: MatrixClient | null = null;

/**
 * Set the global MatrixClient reference
 * This should be called from initMatrix.ts after creating the client
 * @param client - The MatrixClient instance or null to clear
 */
export function setGlobalMatrixClient(client: MatrixClient | null): void {
  globalMatrixClient = client;
}

/**
 * Get the current MatrixClient instance
 * @returns The MatrixClient instance or null if not initialized
 */
export function getGlobalMatrixClient(): MatrixClient | null {
  return globalMatrixClient;
}

/**
 * Update the access token for a session in localStorage
 * This should be called when a token is refreshed by the MatrixClient
 * @param userId - The user ID
 * @param newToken - The new access token
 */
export function updateSessionToken(userId: string, newToken: string): void {
  const sessions = getLocalStorageItem<Sessions>(MATRIX_SESSIONS_KEY, []);
  const sessionIndex = sessions.findIndex((s: Session) => s.userId === userId);
  
  if (sessionIndex >= 0) {
    sessions[sessionIndex] = {
      ...sessions[sessionIndex],
      accessToken: newToken,
    };
    setLocalStorageItem(MATRIX_SESSIONS_KEY, sessions);
  }
}

/**
 * Get the access token for the currently active session.
 * Prioritizes the token from the active MatrixClient instance (most up-to-date),
 * then falls back to localStorage. This ensures we always use the freshest token,
 * even if it's been refreshed by the SDK.
 * 
 * @returns The current access token or undefined if no session is active
 */
export function getCurrentAccessToken(): string | undefined {
  // First try to get the token from the active MatrixClient if available
  // This ensures we get the most up-to-date token, including any refreshed tokens
  if (globalMatrixClient) {
    const clientToken = globalMatrixClient.getAccessToken?.();
    if (clientToken) {
      return clientToken;
    }
  }
  
  // Fall back to localStorage if MatrixClient is not available or doesn't have a token
  const currentUserId = getLocalStorageItem<string | undefined>(CURRENT_SESSION_KEY, undefined);
  
  if (!currentUserId) {
    // Fallback to old single-account storage for migration
    return localStorage.getItem('cinny_access_token') ?? undefined;
  }
  
  const sessions = getLocalStorageItem<Sessions>(MATRIX_SESSIONS_KEY, []);
  const currentSession = sessions.find((s: Session) => s.userId === currentUserId);
  
  return currentSession?.accessToken;
}

/**
 * Get the access token for a specific user.
 * Useful when you need to fetch data for a non-active account.
 * 
 * @param userId - The Matrix user ID
 * @returns The access token for the specified user or undefined
 */
export function getAccessTokenForUser(userId: string): string | undefined {
  const sessions = getLocalStorageItem<Sessions>(MATRIX_SESSIONS_KEY, []);
  const session = sessions.find((s: Session) => s.userId === userId);
  
  return session?.accessToken;
}
