/**
 * PWA Installation Manager
 * 
 * Handles PWA installation flow with cross-browser support.
 * Provides beforeinstallprompt event handling, user engagement detection,
 * and dismissal state management for the install prompt.
 */

import { browser } from '$app/environment';

interface BeforeInstallPromptEvent extends Event {
  prompt(): Promise<void>;
  userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>;
}

export class PWAInstallManager {
  private deferredPrompt: BeforeInstallPromptEvent | null = null;
  private listeners: Array<(canInstall: boolean) => void> = [];
  private installable = false;

  constructor() {
    if (browser) {
      this.initializeInstallPrompt();
    }
  }

  /**
   * Initialize PWA install prompt event listeners
   */
  private initializeInstallPrompt(): void {
    // Listen for beforeinstallprompt event (Chrome, Edge)
    window.addEventListener('beforeinstallprompt', (e: Event) => {
      e.preventDefault();
      this.deferredPrompt = e as BeforeInstallPromptEvent;
      this.installable = true;
      this.notifyListeners(true);
      console.log('[PWA] Install prompt available');
    });

    // Listen for app installation completion
    window.addEventListener('appinstalled', () => {
      console.log('[PWA] App was installed');
      this.installable = false;
      this.deferredPrompt = null;
      this.notifyListeners(false);
      
      // Clear dismissal state since user installed
      this.clearDismissed();
    });

    // Check if already installed
    if (this.isStandalone()) {
      console.log('[PWA] App is already running in standalone mode');
    }
  }

  /**
   * Check if PWA can be installed
   */
  public canInstall(): boolean {
    return this.installable && this.deferredPrompt !== null;
  }

  /**
   * Show the browser's install prompt
   * 
   * @returns Promise resolving to user's choice or 'unavailable' if no prompt available
   */
  public async showInstallPrompt(): Promise<'accepted' | 'dismissed' | 'unavailable'> {
    if (!this.deferredPrompt) {
      console.warn('[PWA] Install prompt not available');
      return 'unavailable';
    }

    try {
      await this.deferredPrompt.prompt();
      const { outcome } = await this.deferredPrompt.userChoice;
      
      this.deferredPrompt = null;
      this.installable = false;
      this.notifyListeners(false);
      
      console.log(`[PWA] Install prompt ${outcome}`);
      return outcome;
    } catch (error) {
      console.error('[PWA] Install prompt failed:', error);
      return 'dismissed';
    }
  }

  /**
   * Register a callback for install state changes
   * 
   * @param callback Function to call when install state changes
   * @returns Unsubscribe function
   */
  public onInstallStateChange(callback: (canInstall: boolean) => void): () => void {
    this.listeners.push(callback);
    
    // Call immediately with current state
    callback(this.canInstall());
    
    return () => {
      this.listeners = this.listeners.filter(cb => cb !== callback);
    };
  }

  /**
   * Notify all listeners of state change
   */
  private notifyListeners(canInstall: boolean): void {
    this.listeners.forEach(callback => {
      try {
        callback(canInstall);
      } catch (error) {
        console.error('[PWA] Error in install state listener:', error);
      }
    });
  }

  /**
   * Check if app is running in standalone mode (already installed)
   */
  public isStandalone(): boolean {
    if (!browser) return false;
    
    return (
      window.matchMedia('(display-mode: standalone)').matches ||
      (window.navigator as any).standalone === true ||
      document.referrer.includes('android-app://')
    );
  }

  /**
   * Check if user has dismissed the install prompt
   */
  public isDismissed(): boolean {
    if (!browser) return false;
    return localStorage.getItem('pwa-install-dismissed') === 'true';
  }

  /**
   * Mark install prompt as dismissed by user
   */
  public setDismissed(): void {
    if (browser) {
      localStorage.setItem('pwa-install-dismissed', 'true');
      console.log('[PWA] Install prompt dismissed by user');
    }
  }

  /**
   * Clear dismissal state (called when app is installed)
   */
  public clearDismissed(): void {
    if (browser) {
      localStorage.removeItem('pwa-install-dismissed');
    }
  }

  /**
   * Get browser-specific installation instructions
   */
  public getInstallInstructions(): string {
    if (!browser) return 'Install instructions not available';

    const userAgent = navigator.userAgent.toLowerCase();
    const isMobile = /android|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent);
    
    if (isMobile && userAgent.includes('safari') && !userAgent.includes('chrome')) {
      return 'Tap the Share button and select "Add to Home Screen"';
    } else if (userAgent.includes('chrome') && !userAgent.includes('edg')) {
      return 'Look for the install button in your browser address bar';
    } else if (userAgent.includes('edg')) {
      return 'Look for the install button in your browser address bar';
    } else if (userAgent.includes('firefox')) {
      return 'Firefox has limited PWA support. Try Chrome or Edge for the best experience';
    }
    
    return 'Check your browser menu for "Install App" or "Add to Home Screen" options';
  }

  /**
   * Get current browser name for UI customization
   */
  public getBrowserName(): string {
    if (!browser) return 'unknown';

    const userAgent = navigator.userAgent.toLowerCase();
    
    if (userAgent.includes('chrome') && !userAgent.includes('edg')) return 'chrome';
    if (userAgent.includes('safari') && !userAgent.includes('chrome')) return 'safari';
    if (userAgent.includes('firefox')) return 'firefox';
    if (userAgent.includes('edg')) return 'edge';
    
    return 'unknown';
  }
}

// Singleton instance for application-wide use
export const pwaInstallManager = new PWAInstallManager();