import { Component, inject, OnInit, signal, effect } from '@angular/core';
import { ThemeService } from './services/theme.service';
import { CantiService } from './services/canti.service';
import { SettingsService } from './services/settings.service';
import { VERSION } from './version';
import { Router, ActivatedRoute } from '@angular/router';
import { ToastController } from '@ionic/angular';
import { SwUpdate, VersionReadyEvent } from '@angular/service-worker';
import { filter, first } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
  standalone: false,
})
export class AppComponent implements OnInit {
  private themeService = inject(ThemeService); // Ensures theme is initialized at boot
  public cantiService = inject(CantiService);
  public settingsService = inject(SettingsService);
  public version = VERSION;
  private router = inject(Router);
  private route = inject(ActivatedRoute);
  private toastCtrl = inject(ToastController);
  private swUpdate = inject(SwUpdate);

  public showRedirectOverlay = signal<boolean>(false);
  public showInstallOverlay = signal<boolean>(false);
  public redirectFailed = signal<boolean>(false);
  public protocolLink = '';

  constructor() {
    // Gli aggiornamenti automatici e periodici sono stati rimossi.
    // L'aggiornamento viene gestito esclusivamente in modo manuale
    // tramite il pulsante "Verifica Aggiornamenti App" in SettingsPage.
    
    effect(() => {
      this.checkLoaderDismissal();
    });
  }

  checkLoaderDismissal() {
    const ready = this.settingsService.isVersionCheckComplete() && this.cantiService.firstLoadCompleted();
    if (!ready) {
      return;
    }

    // Se l'overlay di redirect o di installazione è mostrato, NON nascondiamo il loader iniziale
    // per rimanere nella welcome page mentre l'utente sceglie.
    if (this.showRedirectOverlay() || this.showInstallOverlay()) {
      return;
    }

    // Altrimenti, nascondiamo il loader per far entrare l'utente nell'app
    if ((window as any).PwaLoader) {
      (window as any).PwaLoader.hide();
    }
  }

  async ngOnInit() {
    // Add global horizontal scroll support for wheel on horizontal containers
    window.addEventListener('wheel', (event: WheelEvent) => {
      if (Math.abs(event.deltaY) > 0 && Math.abs(event.deltaX) === 0) {
        const path = event.composedPath();
        for (const target of path) {
          if (target instanceof HTMLElement) {
            const style = window.getComputedStyle(target);
            const isHorizontalScroll = 
              (style.overflowX === 'auto' || style.overflowX === 'scroll') &&
              target.scrollWidth > target.clientWidth;
            
            if (isHorizontalScroll) {
              target.scrollLeft += event.deltaY;
              event.preventDefault();
              break;
            }
          }
        }
      }
    }, { passive: false });

    // 1. Allineamento istantaneo alla versione remota
    if ((window as any).PwaLoader) {
      (window as any).PwaLoader.update({
        phase: 'Fase: Verifica Versione',
        desc: 'Verifica della versione più recente in corso...'
      });
    }

    const updated = await this.checkVersionSync();
    if (updated) {
      return; // Reloading, skip further setup
    }

    // Set signal indicating startup version check is complete
    this.settingsService.isVersionCheckComplete.set(true);

    this.route.queryParams.subscribe(params => {
      const protocolUrl = params['url'];
      if (protocolUrl && protocolUrl.startsWith('web+canti:')) {
        try {
          const cleanUrl = protocolUrl.replace('web+canti://', 'http://localhost/');
          const urlObj = new URL(cleanUrl);
          
          let targetPath = urlObj.pathname;
          if (targetPath === '/open' || targetPath === '//open') {
            targetPath = '/';
          } else if (targetPath.startsWith('/open/')) {
            targetPath = targetPath.substring(5);
          }
          
          const queryParams: any = {};
          urlObj.searchParams.forEach((value, key) => {
            queryParams[key] = value;
          });
          
          this.router.navigate([targetPath], { queryParams, replaceUrl: true });
        } catch (e) {
          console.error('Failed to parse protocol url:', protocolUrl, e);
        }
      }
    });

    this.checkAndRedirectToPwa();
  }

  async checkVersionSync(): Promise<boolean> {
    // Controlla SEMPRE version.json per primo — è il modo più affidabile per
    // rilevare un disallineamento di versione, indipendentemente dallo stato del SW.
    // Su mobile, checkForUpdate() può essere lento o inaffidabile.
    try {
      console.log(`[PWA-Update] Verifica version.json all'avvio (locale=${VERSION})...`);
      const response = await Promise.race([
        fetch(`/version.json?cb=${Date.now()}`, { cache: 'no-store' }),
        new Promise<Response | null>((resolve) => setTimeout(() => resolve(null), 5000))
      ]);
      if (response && response.ok) {
        const data = await response.json();
        if (data && data.version && data.version !== VERSION) {
          console.log(`[PWA-Update] Mismatch rilevato: locale=${VERSION}, remota=${data.version}. Forza aggiornamento...`);
          const overlay = showFullscreenUpdateOverlay();

          // Prova ad attivare tramite SwUpdate se abilitato (scarica il nuovo bundle SW)
          if (this.swUpdate.isEnabled) {
            try {
              const hasSwUpdate = await Promise.race([
                this.swUpdate.checkForUpdate(),
                new Promise<boolean>((resolve) => setTimeout(() => resolve(false), 8000))
              ]);
              if (hasSwUpdate) {
                console.log('[PWA-Update] SW aggiornamento disponibile, attivazione...');
                await Promise.race([
                  this.swUpdate.activateUpdate(),
                  new Promise<void>((resolve) => setTimeout(resolve, 5000))
                ]);
              }
            } catch (e) {
              console.warn('[PWA-Update] SwUpdate durante mismatch fallito:', e);
            }
          }

          // Aggiorna anche la registrazione SW direttamente (doppia sicurezza)
          if ('serviceWorker' in navigator) {
            try {
              const registration = await navigator.serviceWorker.ready;
              await registration.update();
            } catch (e) {
              console.warn('[PWA-Update] SW registration.update fallito:', e);
            }
          }

          // Disattiva service worker attivi per forzare il refresh completo
          if ('serviceWorker' in navigator) {
            const registrations = await navigator.serviceWorker.getRegistrations();
            for (const registration of registrations) {
              await registration.unregister();
            }
          }

          // Cancella le cache del browser
          if ('caches' in window) {
            const keys = await caches.keys();
            for (const key of keys) {
              await caches.delete(key);
            }
          }

          overlay.finish();

          // Ricarica con parametro cache-busting per forzare l'allineamento remoto
          const url = new URL(window.location.href);
          url.searchParams.set('update_cb', Date.now().toString());
          window.location.replace(url.toString());
          return true;
        } else {
          console.log('[PWA-Update] Versione allineata, nessun aggiornamento necessario.');
        }
      }
    } catch (e) {
      console.warn('[PWA-Update] version.json check fallito:', e);
    }

    // 2. Fallback: Prova SwUpdate nel caso in cui il controllo version.json sia fallito o sia stato servito dalla cache
    if (this.swUpdate.isEnabled) {
      try {
        console.log('[PWA-Update] Verifica aggiornamenti via SwUpdate all\'avvio...');

        let activated = false;
        let overlay: any = null;

        const activateAndReload = async () => {
          if (activated) return;
          activated = true;
          try {
            await this.swUpdate.activateUpdate();
          } catch (e) {
            console.warn('[PWA-Update] activateUpdate fallito all\'avvio:', e);
          }

          // Deregistra i vecchi SW e cancella le cache per un ricaricamento pulito
          if ('serviceWorker' in navigator) {
            const registrations = await navigator.serviceWorker.getRegistrations();
            for (const reg of registrations) {
              await reg.unregister();
            }
          }
          if ('caches' in window) {
            const keys = await caches.keys();
            for (const key of keys) {
              await caches.delete(key);
            }
          }

          if (overlay) overlay.finish();
          setTimeout(() => {
            const url = new URL(window.location.href);
            url.searchParams.set('update_cb', Date.now().toString());
            window.location.replace(url.toString());
          }, 600);
        };

        // Sottoscrivi PRIMA di verificare l'aggiornamento per evitare race condition
        const sub = this.swUpdate.versionUpdates
          .pipe(
            filter((evt): evt is VersionReadyEvent => evt.type === 'VERSION_READY'),
            first()
          )
          .subscribe(() => {
            console.log('[PWA-Update] VERSION_READY ricevuto all\'avvio');
            activateAndReload();
          });

        // Concedi fino a 8 secondi al controllo SW — le connessioni mobili possono essere lente
        const hasUpdate = await Promise.race([
          this.swUpdate.checkForUpdate(),
          new Promise<boolean>((resolve) => setTimeout(() => resolve(false), 8000))
        ]);

        if (hasUpdate) {
          console.log('[PWA-Update] Aggiornamento rilevato via SwUpdate. Avvio download...');
          overlay = showFullscreenUpdateOverlay();

          // Timeout di sicurezza di 25 secondi: se VERSION_READY non arriva, attiva comunque
          setTimeout(() => {
            console.log('[PWA-Update] Safety timeout raggiunto all\'avvio, procedo...');
            sub.unsubscribe();
            activateAndReload();
          }, 25000);

          return true; // Attendi il ricaricamento
        } else {
          sub.unsubscribe();
        }
      } catch (err) {
        console.warn('[PWA-Update] Controllo SwUpdate fallito all\'avvio:', err);
      }
    }

    return false;
  }

  async checkAndRedirectToPwa() {
    const isStandalone = window.matchMedia('(display-mode: standalone)').matches || (navigator as any).standalone;
    if (isStandalone) {
      localStorage.setItem('pwa-installed', 'true');
      return;
    }

    const search = window.location.search;
    const path = window.location.pathname;
    this.protocolLink = `web+canti://open${path}${search}`;

    // Controlliamo se abbiamo già salvato che l'app è installata o se possiamo verificarlo
    let isInstalled = localStorage.getItem('pwa-installed') === 'true';
    if (!isInstalled && 'getInstalledRelatedApps' in navigator) {
      try {
        const relatedApps = await (navigator as any).getInstalledRelatedApps();
        isInstalled = relatedApps.length > 0;
        if (isInstalled) {
          localStorage.setItem('pwa-installed', 'true');
        }
      } catch (e) {
        console.warn('Failed to check installed apps:', e);
      }
    }

    if (isInstalled) {
      const skipRedirect = sessionStorage.getItem('skip-pwa-redirect') === 'true';
      if (!skipRedirect) {
        this.showRedirectOverlay.set(true);
        this.redirectFailed.set(false);
        if ((window as any).PwaLoader) {
          (window as any).PwaLoader.update({ isRedirect: true });
        }
        // Tentiamo il reindirizzamento automatico
        setTimeout(() => {
          window.location.href = this.protocolLink;
          
          // Se dopo 2 secondi l'utente è ancora qui, probabilmente l'app non è installata
          setTimeout(() => {
            if (this.showRedirectOverlay()) {
              this.redirectFailed.set(true);
              localStorage.setItem('pwa-installed', 'false');
              if ((window as any).PwaLoader) {
                (window as any).PwaLoader.hide();
              }
            }
          }, 2000);
        }, 800);
      }
    } else {
      // Se non è installata, proponiamo l'installazione immediata per evitare la cache del browser e avere un'esperienza ottimale
      const skipInstall = sessionStorage.getItem('skip-pwa-install') === 'true';
      const isMobile = this.settingsService.isAndroid() || this.settingsService.isIos();
      const hasDesktopPrompt = this.settingsService.showInstallButton() || this.settingsService.deferredPrompt();
      if (!skipInstall && (isMobile || hasDesktopPrompt)) {
        this.showInstallOverlay.set(true);
      }
    }
  }

  openPwaManual() {
    window.location.href = this.protocolLink;
    if ((window as any).PwaLoader) {
      (window as any).PwaLoader.show();
      (window as any).PwaLoader.update({ isRedirect: true });
    }
    // Se dopo 2 secondi l'utente è ancora qui, probabilmente l'app non è installata
    setTimeout(() => {
      if (this.showRedirectOverlay()) {
        this.redirectFailed.set(true);
        localStorage.setItem('pwa-installed', 'false');
        if ((window as any).PwaLoader) {
          (window as any).PwaLoader.hide();
        }
      }
    }, 2000);
  }

  stayInBrowser() {
    sessionStorage.setItem('skip-pwa-redirect', 'true');
    this.showRedirectOverlay.set(false);
  }

  closeInstallOverlay() {
    sessionStorage.setItem('skip-pwa-install', 'true');
    this.showInstallOverlay.set(false);
  }

  async triggerInstall() {
    await this.settingsService.installPwa();
    this.closeInstallOverlay();
  }

  async triggerInstallFromRedirect() {
    await this.settingsService.installPwa();
    sessionStorage.setItem('skip-pwa-redirect', 'true');
    this.showRedirectOverlay.set(false);
  }
}

export function showFullscreenUpdateOverlay() {
  if ((window as any).PwaLoader) {
    (window as any).PwaLoader.show();
    (window as any).PwaLoader.update({
      title: 'Download aggiornamento',
      phase: 'Fase: Download',
      desc: 'Scaricamento della nuova versione...',
      percent: 0
    });
  }

  // Fetch remote version to display the version being downloaded
  fetch(`/version.json?cb=${Date.now()}`)
    .then(res => {
      if (res.ok) return res.json();
      throw new Error('Fallback');
    })
    .then(data => {
      if (data && data.version && (window as any).PwaLoader) {
        (window as any).PwaLoader.update({
          version: 'Versione ' + data.version
        });
      }
    })
    .catch(() => {});

  let percent = 0;
  const interval = setInterval(() => {
    if (percent < 95) {
      percent += Math.floor(Math.random() * 5) + 2;
      if (percent > 95) percent = 95;
      if ((window as any).PwaLoader) {
        (window as any).PwaLoader.update({ percent });
      }
    }
  }, 150);

  return {
    finish: () => {
      clearInterval(interval);
      if ((window as any).PwaLoader) {
        (window as any).PwaLoader.update({ percent: 100 });
      }
    }
  };
}
