import { Component, inject, ApplicationRef } from '@angular/core';
import { SwUpdate, VersionReadyEvent } from '@angular/service-worker';
import { filter, first } from 'rxjs/operators';
import { concat, interval, fromEvent } from 'rxjs';
import { ToastController } from '@ionic/angular';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
  standalone: false,
})
export class AppComponent {
  private swUpdate = inject(SwUpdate);
  private appRef = inject(ApplicationRef);
  private toastCtrl = inject(ToastController);

  constructor() {
    this.setupUpdates();
  }

  private async forceBypassCacheAndCheck(): Promise<boolean> {
    try {
      // 1. Forza il browser mobile a controllare la rete per aggiornamenti al Service Worker nativo
      if ('serviceWorker' in navigator) {
        const registrations = await navigator.serviceWorker.getRegistrations();
        for (const registration of registrations) {
          await registration.update();
          console.log('[PWA-Update] Native Service Worker updated');
        }
      }
      // 2. Forza il caricamento di ngsw.json bypassando le cache intermedie e locali
      await fetch(`/ngsw.json?cb=${Date.now()}`, { cache: 'no-store' });
      await fetch('/ngsw.json', { cache: 'reload' });
      console.log('[PWA-Update] Caches successfully busted for ngsw.json');
    } catch (e) {
      console.warn('[PWA-Update] Failed to bust cache for ngsw.json:', e);
    }
    return await this.swUpdate.checkForUpdate();
  }

  private setupUpdates() {
    if (this.swUpdate.isEnabled) {
      const launchTime = Date.now();

      // Ricarica automaticamente se il Service Worker controller cambia per garantire la freschezza immediata
      if ('serviceWorker' in navigator) {
        navigator.serviceWorker.addEventListener('controllerchange', () => {
          console.log('[PWA-Update] Controller changed. Reloading page...');
          window.location.reload();
        });
      }

      // 1. Sottoscrizione all'evento di versione scaricata/pronta
      this.swUpdate.versionUpdates
        .pipe(filter((evt): evt is VersionReadyEvent => evt.type === 'VERSION_READY'))
        .subscribe(async () => {
          const timeSinceLaunch = Date.now() - launchTime;
          console.log(`[PWA-Update] New version ready! Time since launch: ${timeSinceLaunch}ms`);

          if (timeSinceLaunch < 8000) {
            // Se l'applicazione è appena stata aperta (< 8s), la aggiorniamo ed eseguiamo il reload immediato e silenzioso
            console.log('[PWA-Update] Auto-activating update on startup...');
            try {
              await this.swUpdate.activateUpdate();
              console.log('[PWA-Update] Update activated successfully, reloading page...');
              window.location.reload();
            } catch (err) {
              console.error('[PWA-Update] Auto-activation failed on startup:', err);
              // Fallback: ricarica comunque per provare a forzare l'attivazione
              window.location.reload();
            }
          } else {
            // Altrimenti mostriamo il prompt interattivo per evitare interruzioni improvvise
            console.log('[PWA-Update] Showing toast prompt for active user...');
            const toast = await this.toastCtrl.create({
              message: 'Nuova versione dell\'applicazione disponibile!',
              position: 'bottom',
              color: 'secondary',
              buttons: [
                {
                  text: 'Aggiorna',
                  role: 'cancel',
                  handler: () => {
                    console.log('[PWA-Update] Activating update and reloading...');
                    this.swUpdate.activateUpdate().then(() => {
                       window.location.replace(window.location.origin + window.location.pathname + '?update=' + Date.now());
                    });
                  }
                }
              ]
            });
            await toast.present();
          }
        });

      // 2. Controllo IMMEDIATO all'avvio dell'applicazione (senza attendere lo stato isStable)
      console.log('[PWA-Update] Startup: Checking for PWA updates immediately...');
      this.forceBypassCacheAndCheck().catch(err => {
        console.warn('[PWA-Update] Startup update check failed:', err);
      });

      // 3. Attiva i controlli periodici in background solo DOPO la stabilizzazione dell'app
      this.appRef.isStable.pipe(
        filter(stable => stable),
        first()
      ).subscribe(() => {
        console.log('[PWA-Update] App is stable. Initializing background updates...');
        
        // Controllo periodico ogni 60 secondi
        const every60Seconds$ = interval(60 * 1000);
        every60Seconds$.subscribe(async () => {
          console.log('[PWA-Update] Periodic check for updates (every 60s)...');
          try {
            await this.forceBypassCacheAndCheck();
          } catch (err) {
            console.warn('[PWA-Update] Periodic update check failed:', err);
          }
        });
      });

      // 4. Controllo quando l'utente torna sulla scheda o ripristina l'app (Visibility Change)
      fromEvent(document, 'visibilitychange')
        .pipe(filter(() => document.visibilityState === 'visible'))
        .subscribe(async () => {
          console.log('[PWA-Update] App resumed, checking for PWA updates...');
          try {
            await this.forceBypassCacheAndCheck();
          } catch (err) {
            console.warn('[PWA-Update] Resume update check failed:', err);
          }
        });
    }
  }
}
