/**
 * @ai-summary Authentication gate to ensure API requests wait for auth initialization
 * @ai-context Prevents race conditions between IndexedDB init and API calls
 */

import { useState, useEffect } from 'react';

// Global authentication readiness state
let authInitialized = false;
let authInitPromise: Promise<void> | null = null;
let resolveAuthInit: (() => void) | null = null;

// Debug logging
console.log('[Auth Gate] Module loaded, authInitialized:', authInitialized);

// Request queue to hold requests until auth is ready
interface QueuedRequest {
  resolve: (value: any) => void;
  reject: (error: any) => void;
  requestFn: () => Promise<any>;
}

let requestQueue: QueuedRequest[] = [];
let isProcessingQueue = false;

export const waitForAuthInit = (): Promise<void> => {
  if (authInitialized) {
    return Promise.resolve();
  }

  if (!authInitPromise) {
    authInitPromise = new Promise((resolve) => {
      resolveAuthInit = resolve;
    });
  }

  return authInitPromise;
};

export const setAuthInitialized = (initialized: boolean) => {
  console.log('[DEBUG] setAuthInitialized called with:', initialized, '(was:', authInitialized, ')');
  authInitialized = initialized;

  if (initialized) {
    console.log('[DEBUG Auth Gate] Authentication fully initialized');

    // Resolve the auth promise
    if (resolveAuthInit) {
      resolveAuthInit();
      resolveAuthInit = null;
    }

    // Process any queued requests
    processRequestQueue();
  } else {
    // Reset state when auth becomes unavailable
    authInitPromise = null;
    resolveAuthInit = null;
    requestQueue = [];
  }
};

export const isAuthInitialized = () => authInitialized;

// Queue a request until auth is ready
export const queueRequest = <T>(requestFn: () => Promise<T>): Promise<T> => {
  if (authInitialized) {
    return requestFn();
  }

  return new Promise((resolve, reject) => {
    requestQueue.push({
      resolve,
      reject,
      requestFn
    });

    console.log(`[Auth Gate] Queued request, ${requestQueue.length} total in queue`);
  });
};

// Process all queued requests
const processRequestQueue = async () => {
  if (isProcessingQueue || requestQueue.length === 0) {
    return;
  }

  isProcessingQueue = true;
  console.log(`[Auth Gate] Processing ${requestQueue.length} queued requests`);

  const queueToProcess = [...requestQueue];
  requestQueue = [];

  for (const { resolve, reject, requestFn } of queueToProcess) {
    try {
      const result = await requestFn();
      resolve(result);
    } catch (error) {
      reject(error);
    }
  }

  isProcessingQueue = false;
  console.log('[Auth Gate] Finished processing queued requests');
};

/**
 * React hook to track auth initialization state
 * Returns true once auth is fully initialized with token
 * Uses polling with exponential backoff to detect state changes
 */
export const useIsAuthInitialized = () => {
  const [initialized, setInitialized] = useState(isAuthInitialized());

  useEffect(() => {
    // If already initialized, no need to wait
    if (isAuthInitialized()) {
      console.log('[useIsAuthInitialized] Already initialized');
      setInitialized(true);
      return;
    }

    // Poll for initialization with exponential backoff
    console.log('[useIsAuthInitialized] Starting poll for auth init');
    let pollCount = 0;
    const maxPolls = 50; // 5 seconds with exponential backoff

    const pollAuthInit = () => {
      pollCount++;
      const isInit = isAuthInitialized();
      console.log(`[useIsAuthInitialized] Poll #${pollCount}: initialized=${isInit}`);

      if (isInit) {
        console.log('[useIsAuthInitialized] Auth initialized via poll!');
        setInitialized(true);
        return;
      }

      if (pollCount >= maxPolls) {
        console.warn('[useIsAuthInitialized] Max polls reached, assuming initialized');
        setInitialized(true);
        return;
      }

      // Exponential backoff: 50ms, 100ms, 200ms, 400ms, etc.
      const delay = Math.min(50 * Math.pow(1.5, pollCount - 1), 2000);
      setTimeout(pollAuthInit, delay);
    };

    // Start polling after a small delay to let TokenInjector run
    setTimeout(pollAuthInit, 100);
  }, []);

  return initialized;
};