/**
 * Client-side verification state management with circuit breaker pattern
 * Prevents endless reload loops on mobile browsers
 */

export interface VerificationAttempt {
  token: string;
  attempts: number;
  lastAttempt: number;
  maxAttempts: number;
  status: 'pending' | 'success' | 'failed' | 'blocked';
  errors: string[];
}

const STORAGE_KEY = 'email_verification_state';
const MAX_ATTEMPTS_DEFAULT = 3;
const ATTEMPT_WINDOW = 5 * 60 * 1000; // 5 minutes
const CIRCUIT_BREAKER_TIMEOUT = 10 * 60 * 1000; // 10 minutes

/**
 * Get verification state for a token
 */
export function getVerificationState(token: string): VerificationAttempt | null {
  if (typeof window === 'undefined' || !token) return null;

  try {
    const stored = sessionStorage.getItem(`${STORAGE_KEY}_${token.substring(0, 10)}`);
    if (!stored) return null;

    const state = JSON.parse(stored) as VerificationAttempt;
    
    // Check if circuit breaker timeout has passed
    const now = Date.now();
    if (state.status === 'blocked' && (now - state.lastAttempt) > CIRCUIT_BREAKER_TIMEOUT) {
      console.log('[verification-state] Circuit breaker timeout passed, resetting state');
      clearVerificationState(token);
      return null;
    }

    return state;
  } catch (error) {
    console.warn('[verification-state] Failed to parse stored state:', error);
    return null;
  }
}

/**
 * Initialize or update verification state
 */
export function initVerificationState(token: string, maxAttempts: number = MAX_ATTEMPTS_DEFAULT): VerificationAttempt {
  if (typeof window === 'undefined' || !token) {
    throw new Error('Cannot initialize verification state: no window or token');
  }

  const existing = getVerificationState(token);
  if (existing) {
    return existing;
  }

  const state: VerificationAttempt = {
    token,
    attempts: 0,
    lastAttempt: 0,
    maxAttempts,
    status: 'pending',
    errors: []
  };

  try {
    sessionStorage.setItem(`${STORAGE_KEY}_${token.substring(0, 10)}`, JSON.stringify(state));
    console.log('[verification-state] Initialized verification state for token');
    return state;
  } catch (error) {
    console.error('[verification-state] Failed to save state:', error);
    return state;
  }
}

/**
 * Record a verification attempt
 */
export function recordAttempt(token: string, success: boolean = false, error?: string): VerificationAttempt {
  if (typeof window === 'undefined' || !token) {
    throw new Error('Cannot record attempt: no window or token');
  }

  const state = getVerificationState(token) || initVerificationState(token);
  const now = Date.now();

  // Check if we're within the attempt window
  if (state.lastAttempt > 0 && (now - state.lastAttempt) > ATTEMPT_WINDOW) {
    console.log('[verification-state] Attempt window expired, resetting counter');
    state.attempts = 0;
    state.errors = [];
  }

  state.attempts++;
  state.lastAttempt = now;

  if (success) {
    state.status = 'success';
    console.log('[verification-state] Verification successful, clearing state');
    // Don't clear immediately - let the navigation complete first
    setTimeout(() => clearVerificationState(token), 1000);
  } else {
    if (error) {
      state.errors.push(error);
    }

    if (state.attempts >= state.maxAttempts) {
      state.status = 'blocked';
      console.log(`[verification-state] Maximum attempts (${state.maxAttempts}) reached, blocking further attempts`);
    } else {
      state.status = 'failed';
      console.log(`[verification-state] Attempt ${state.attempts}/${state.maxAttempts} failed`);
    }
  }

  try {
    sessionStorage.setItem(`${STORAGE_KEY}_${token.substring(0, 10)}`, JSON.stringify(state));
  } catch (error) {
    console.error('[verification-state] Failed to update state:', error);
  }

  return state;
}

/**
 * Check if verification should be blocked
 */
export function shouldBlockVerification(token: string): boolean {
  if (typeof window === 'undefined' || !token) return false;

  const state = getVerificationState(token);
  if (!state) return false;

  if (state.status === 'blocked') {
    const timeRemaining = CIRCUIT_BREAKER_TIMEOUT - (Date.now() - state.lastAttempt);
    if (timeRemaining > 0) {
      console.log(`[verification-state] Verification blocked for ${Math.ceil(timeRemaining / 1000 / 60)} more minutes`);
      return true;
    }
  }

  return state.status === 'success' || (state.attempts >= state.maxAttempts && state.status !== 'pending');
}

/**
 * Clear verification state for a token
 */
export function clearVerificationState(token: string): void {
  if (typeof window === 'undefined' || !token) return;

  try {
    sessionStorage.removeItem(`${STORAGE_KEY}_${token.substring(0, 10)}`);
    console.log('[verification-state] Cleared verification state');
  } catch (error) {
    console.warn('[verification-state] Failed to clear state:', error);
  }
}

/**
 * Get user-friendly status message
 */
export function getStatusMessage(state: VerificationAttempt | null): string {
  if (!state) return '';

  switch (state.status) {
    case 'pending':
      return '';
    case 'success':
      return 'Email verified successfully!';
    case 'failed':
      if (state.attempts === 1) {
        return 'Verification failed. Retrying...';
      }
      return `Verification failed (${state.attempts}/${state.maxAttempts} attempts). ${state.maxAttempts - state.attempts} attempts remaining.`;
    case 'blocked':
      const timeRemaining = Math.ceil((CIRCUIT_BREAKER_TIMEOUT - (Date.now() - state.lastAttempt)) / 1000 / 60);
      return `Too many failed attempts. Please wait ${timeRemaining} minutes before trying again, or contact support.`;
    default:
      return '';
  }
}

/**
 * Progressive navigation with fallbacks for mobile browsers
 */
export async function navigateWithFallback(url: string, options: { replace?: boolean } = {}): Promise<boolean> {
  if (typeof window === 'undefined') return false;

  console.log(`[verification-state] Attempting navigation to: ${url}`);

  try {
    // Method 1: Use Nuxt navigateTo
    if (typeof navigateTo === 'function') {
      console.log('[verification-state] Using navigateTo');
      await navigateTo(url, options);
      return true;
    }
  } catch (error) {
    console.warn('[verification-state] navigateTo failed:', error);
  }

  try {
    // Method 2: Use Vue Router (if available)
    const nuxtApp = (window as any)?.$nuxt;
    if (nuxtApp?.$router) {
      console.log('[verification-state] Using Vue Router');
      if (options.replace) {
        await nuxtApp.$router.replace(url);
      } else {
        await nuxtApp.$router.push(url);
      }
      return true;
    }
  } catch (error) {
    console.warn('[verification-state] Vue Router failed:', error);
  }

  // Method 3: Direct window.location (mobile fallback)
  console.log('[verification-state] Using window.location fallback');
  if (options.replace) {
    window.location.replace(url);
  } else {
    window.location.href = url;
  }
  
  return true;
}

/**
 * Mobile-specific delay before navigation to ensure stability
 */
export function getMobileNavigationDelay(): number {
  if (typeof window === 'undefined') return 0;

  // Detect mobile browsers
  const isMobile = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
  const isSafari = /Safari/i.test(navigator.userAgent) && !/Chrome/i.test(navigator.userAgent);
  
  if (isMobile && isSafari) {
    return 500; // Extra delay for Safari on iOS
  } else if (isMobile) {
    return 300; // Standard mobile delay
  }
  
  return 100; // Minimal delay for desktop
}

/**
 * Clean up all expired verification states
 */
export function cleanupExpiredStates(): void {
  if (typeof window === 'undefined') return;

  try {
    const now = Date.now();
    const keysToRemove: string[] = [];

    for (let i = 0; i < sessionStorage.length; i++) {
      const key = sessionStorage.key(i);
      if (!key?.startsWith(STORAGE_KEY)) continue;

      try {
        const stored = sessionStorage.getItem(key);
        if (!stored) continue;

        const state = JSON.parse(stored) as VerificationAttempt;
        
        // Remove states older than circuit breaker timeout
        if ((now - state.lastAttempt) > CIRCUIT_BREAKER_TIMEOUT) {
          keysToRemove.push(key);
        }
      } catch (error) {
        // Remove invalid stored data
        keysToRemove.push(key);
      }
    }

    keysToRemove.forEach(key => {
      sessionStorage.removeItem(key);
    });

    if (keysToRemove.length > 0) {
      console.log(`[verification-state] Cleaned up ${keysToRemove.length} expired verification states`);
    }
  } catch (error) {
    console.warn('[verification-state] Failed to cleanup expired states:', error);
  }
}

// Auto-cleanup on page load
if (typeof window !== 'undefined') {
  // Clean up immediately
  cleanupExpiredStates();
  
  // Clean up periodically
  setInterval(cleanupExpiredStates, 5 * 60 * 1000); // Every 5 minutes
}
