import { Component, computed, signal, inject, effect, OnDestroy } from '@angular/core';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
import { CantiService } from '../services/canti.service';
import { Router, ActivatedRoute } from '@angular/router';
import { AudioEngineService } from '../services/audio-engine.service';
import { ThemeService } from '../services/theme.service';
import { ConnectivityService } from '../services/connectivity.service';
import { PlaylistService } from '../services/playlist.service';
import { SettingsService } from '../services/settings.service';
import { VERSION } from '../version';
import { YoutubePlayerService } from '../services/youtube-player.service';
import { ModalController, AlertController, ToastController, LoadingController } from '@ionic/angular';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { MyCantiService } from '../services/my-canti.service';
import { QrScannerComponent } from '../components/qr-scanner/qr-scanner.component';
import { CantiLettureService } from '../services/canti-letture.service';
import { ComunitaService } from '../services/comunita.service';
import { environment } from '../../environments/environment';
import { SwUpdate, VersionReadyEvent } from '@angular/service-worker';
import { filter, first } from 'rxjs/operators';
import { showFullscreenUpdateOverlay } from '../app.component';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
  standalone: false,
})
export class HomePage implements OnDestroy {
  public searchQuery = signal<string>('');
  public selectedLiturgico = signal<number | null>(null);
  public selectedTematico = signal<number | null>(null);
  public showOnlyMine = signal<boolean>(false);
  public showTopTen = signal<boolean>(false);
  public showSuggeriti = signal<boolean>(false);
  public showValidati = signal<boolean>(false);
  public showNonValidati = signal<boolean>(false);
  public isMassCardExpanded = signal<boolean>(false);
  public activeFilterType = signal<'liturgico' | 'tematico' | 'playlist' | 'lista_completa' | null>(null);
  public loadedThumbs = new Set<string>();
  public version = VERSION;
  public appName = environment.appName;
  public isAddingSongs = signal<boolean>(false);
  public reorderList = signal<any[]>([]);
  public limit = signal<number>(30);
  public hasUpdateAvailable = signal<boolean>(false);
  
  public fontSize = signal<number>(1.0);
  public youtubePlayerService = inject(YoutubePlayerService);
  public comunitaService = inject(ComunitaService);
  public isSeeking = false;

  private readonly MIN_FONT = 0.6;
  private readonly MAX_FONT = 5.0;
  private initialPinchDistance: number | null = null;
  private initialFontSize: number = 1.0;
  
  private sanitizer = inject(DomSanitizer);
  public audioEngine = inject(AudioEngineService);
  public themeService = inject(ThemeService);
  public connectivityService = inject(ConnectivityService);
  public cantiService = inject(CantiService);
  public myCantiService = inject(MyCantiService);
  public playlistService = inject(PlaylistService);
  public settingsService = inject(SettingsService);
  public cantiLettureService = inject(CantiLettureService);
  private router = inject(Router);
  private route = inject(ActivatedRoute);
  private modalCtrl = inject(ModalController);
  private alertCtrl = inject(AlertController);
  private toastCtrl = inject(ToastController);
  private loadingCtrl = inject(LoadingController);
  private swUpdate = inject(SwUpdate);

  private firstInteraction = true;
  private updatePollInterval: any = null;
  private queryParamsSubscription: any = null;

  async checkForAppUpdate(event?: Event) {
    if (event) event.stopPropagation();
    
    if (!this.swUpdate.isEnabled) {
      const toast = await this.toastCtrl.create({
        message: 'Aggiornamenti non supportati su questo browser.',
        duration: 3000,
        color: 'medium'
      });
      await toast.present();
      return;
    }

    const toastLoading = await this.toastCtrl.create({
      message: 'Ricerca aggiornamenti in corso...',
      duration: 1500,
      color: 'secondary'
    });
    await toastLoading.present();

    const updateAvailable = await this.performUpdateCheck();

    if (!updateAvailable) {
      const toast = await this.toastCtrl.create({
        message: 'L\'applicazione è già aggiornata all\'ultima versione.',
        duration: 3000,
        color: 'success'
      });
      await toast.present();
    }
  }

  private async performUpdateCheck(): Promise<boolean> {
    try {
      if ('serviceWorker' in navigator) {
        const registration = await navigator.serviceWorker.ready;
        await registration.update();
      }

      let sub: any = null;
      let readyPromise: Promise<void> | undefined = undefined;
      
      if (this.swUpdate.isEnabled) {
        readyPromise = new Promise<void>((resolve) => {
          sub = this.swUpdate.versionUpdates
            .pipe(
              filter((evt): evt is VersionReadyEvent => evt.type === 'VERSION_READY'),
              first()
            )
            .subscribe(() => {
              resolve();
            });
        });
      }

      if (this.swUpdate.isEnabled) {
        const swFoundUpdate = await this.swUpdate.checkForUpdate();
        if (swFoundUpdate) {
          await this.applyUpdateAndReload(readyPromise, sub);
          return true;
        }
      }

      if (sub) sub.unsubscribe();

      const versionMismatch = await this.checkVersionJson();
      if (versionMismatch) {
        await this.applyUpdateAndReload();
        return true;
      }

      return false;
    } catch (err) {
      console.error('[PWA-Update] Update check failed from home:', err);
      const toast = await this.toastCtrl.create({
        message: 'Errore durante la ricerca di aggiornamenti.',
        duration: 3000,
        color: 'danger'
      });
      await toast.present();
      return false;
    }
  }

  private async applyUpdateAndReload(readyPromise?: Promise<void>, subscription?: any) {
    const overlay = showFullscreenUpdateOverlay();

    let activated = false;
    const activateAndReload = async () => {
      if (activated) return;
      activated = true;
      try {
        if (this.swUpdate.isEnabled) {
          await this.swUpdate.activateUpdate();
        }
      } catch (e) {
        console.warn('[PWA-Update] activateUpdate failed:', e);
      }
      overlay.finish();
      setTimeout(() => {
        window.location.replace(window.location.origin + window.location.pathname + '?update=' + Date.now());
      }, 600);
    };

    if (readyPromise) {
      Promise.race([
        readyPromise,
        new Promise((resolve) => setTimeout(resolve, 25000))
      ]).then(() => {
        if (subscription) subscription.unsubscribe();
        activateAndReload();
      });
    } else {
      setTimeout(() => {
        activateAndReload();
      }, 1000);
    }
  }

  private async checkVersionJson(): Promise<boolean> {
    try {
      const response = await fetch(`/version.json?cb=${Date.now()}`, { cache: 'no-store' });
      if (!response.ok) return false;
      const data = await response.json();
      return data.version !== VERSION;
    } catch (err) {
      return false;
    }
  }

  private async checkUpdateStatus() {
    try {
      if (this.swUpdate.isEnabled) {
        const swFoundUpdate = await this.swUpdate.checkForUpdate().catch(() => false);
        if (swFoundUpdate) {
          this.hasUpdateAvailable.set(true);
          return;
        }
      }
      const mismatch = await this.checkVersionJson();
      if (mismatch) {
        this.hasUpdateAvailable.set(true);
      }
    } catch (err) {
      console.warn('Failed to check for updates on startup:', err);
    }
  }

  onInteraction() {
    if (this.firstInteraction) {
      this.firstInteraction = false;
    }
  }

  private scrollEffect = effect(() => {
    const activeId = this.youtubePlayerService.currentCantoId();
    const list = this.filteredCanti();
    
    if (activeId) {
      const index = list.findIndex(c => c.id === activeId);
      if (index !== -1 && index >= this.limit()) {
        this.limit.set(index + 15);
      }
      
      // Delay slightly to ensure DOM is updated and classes are applied
      setTimeout(() => {
        const element = document.getElementById('canto-' + activeId);
        if (element) {
          element.scrollIntoView({ behavior: 'smooth', block: 'center' });
        }
      }, 500);
    }
  }, { allowSignalWrites: true });

  private normalize(str: string | undefined): string {
    if (!str) return '';
    return str
      .toLowerCase()
      .replace(/[’'‘’´`]/g, "'")
      .normalize('NFD')
      .replace(/[\u0300-\u036f]/g, '')
      .replace(/hallelujah/g, 'alleluia')
      .replace(/halleluja/g, 'alleluia')
      .replace(/alleluja/g, 'alleluia');
  }

  public filteredCanti = computed(() => {
    const query = this.normalize(this.searchQuery());
    const litId = this.selectedLiturgico();
    const temId = this.selectedTematico();
    const onlyMine = this.showOnlyMine();
    const topTen = this.showTopTen();
    const suggeriti = this.showSuggeriti();
    const activeIds = this.playlistService.activeListIds();
    const selectionMode = this.playlistService.selectionMode();

    // 1. Get base list depending on community filter
    let list: any[] = [];
    const comunitaCode = this.comunitaService.comunitaCode();
    const comunitaIds = this.comunitaService.comunitaCantiIds();

    if (comunitaCode && this.comunitaService.isFilterActive()) {
      // Base is standard canti + my canti + community custom canti + remote custom canti + remote share canti
      list = [
        ...this.cantiService.canti(),
        ...this.myCantiService.myCanti(),
        ...this.playlistService.remoteCustomSongs(),
        ...this.playlistService.remoteShareCanti(),
        ...this.comunitaService.comunitaCantiPersonali()
      ];

      // Filter to only community canti, but preserve canti that are in the active playlist
      list = list.filter(c => {
        return comunitaIds.includes(c.id_canti) || comunitaIds.includes(c.id) || activeIds.includes(c.id);
      });

      // Deduplicate: parish-customized versions take precedence
      const seen = new Map<number | string, any>();
      for (const canto of list) {
        const key = canto.id_canti || canto.id;
        const existing = seen.get(key);
        if (!existing) {
          seen.set(key, canto);
        } else {
          if (!existing.isPersonal && canto.isPersonal) {
            seen.set(key, canto);
          }
        }
      }
      list = Array.from(seen.values());

      // Sort by community song number (num_canto)
      const cantiInfo = this.comunitaService.comunitaCantiInfo();
      list.sort((a, b) => {
        const infoA = cantiInfo.find(x => x.id_canti === a.id_canti || x.id_canti === Number(a.id));
        const infoB = cantiInfo.find(x => x.id_canti === b.id_canti || x.id_canti === Number(b.id));
        const numA = infoA ? Number(infoA.num_canto) : 999999;
        const numB = infoB ? Number(infoB.num_canto) : 999999;
        return numA - numB;
      });
    } else {
      // General context: only standard canti + my canti + remote custom canti + remote share canti
      list = [
        ...this.cantiService.canti(),
        ...this.myCantiService.myCanti(),
        ...this.playlistService.remoteCustomSongs(),
        ...this.playlistService.remoteShareCanti()
      ];
    }

    // 2. Cumulative filtering

    // Filter by selectionMode / reorderList if in selection mode and not adding songs
    if (selectionMode && !this.isAddingSongs()) {
      return this.reorderList();
    }

    // A. Filter by Playlist (if activeIds is present)
    if (activeIds.length > 0 && (!selectionMode || this.playlistService.activePlaylistId() === null)) {
      list = activeIds
        .map(id => list.find(c => c.id === id))
        .filter((c): c is any => !!c);
    }

    // B. Filter by "Only Mine" (Miei)
    if (onlyMine) {
      const myIds = new Set(this.myCantiService.myCanti().map(c => c.id));
      list = list.filter(c => myIds.has(c.id));
    }

    // Filter by Validati (non personali e non contrassegnati come non validati)
    if (this.showValidati()) {
      list = list.filter(c => !c.nonValidato && !c.id.startsWith('my_'));
    }

    // Filter by Non-Validati (personali o esplicitamente non validati)
    if (this.showNonValidati()) {
      list = list.filter(c => c.nonValidato || c.id.startsWith('my_'));
    }

    // C. Filter by Liturgical Moment
    if (litId !== null) {
      list = list.filter(c => c.id_momenti?.includes(litId));
    }

    // D. Filter by Thematic Moment
    if (temId !== null) {
      list = list.filter(c => c.id_momenti?.includes(temId));
    }

    // E. Filter by Suggested (Suggeriti)
    if (suggeriti) {
      const suggMap = this.cantiLettureService.suggestionsMap();
      list = list.filter(c => suggMap.has(c.id_canti));
    }

    // F. Filter by Search Query
    if (query) {
      const processedQuery = query.replace(/\buno\b/g, '1');
      const numberMatchPattern = processedQuery.match(/^(?:numero|nr\.?)\s*(\d+)$/);
      
      if (numberMatchPattern) {
        const targetId = numberMatchPattern[1];
        list = list.filter(c => {
          const commNum = this.getCommunitySongNumber(c);
          return commNum ? commNum === targetId : c.id_canti.toString() === targetId;
        });
      } else {
        list = list.filter(c => {
          const titleMatch = this.normalize(c.titolo).includes(query);
          const authorMatch = this.normalize(c.autore).includes(query);
          const commNum = this.getCommunitySongNumber(c);
          const numberMatch = commNum ? commNum.includes(query) : c.id_canti.toString().includes(query);
          
          const lyricsPlain = (c.testo || '')
            .replace(/{.*?}/g, '')
            .replace(/\n/g, ' ');
          const lyricsMatch = this.normalize(lyricsPlain).includes(query);
          
          return titleMatch || authorMatch || lyricsMatch || numberMatch;
        });
      }
    }

    // G. Sorting/Ordering
    if (topTen) {
      const eseguiti = this.cantiService.cantiEseguiti();
      const eseguitiMap = new Map<number, number>();
      eseguiti.forEach(x => eseguitiMap.set(x.id_canti, x.num));

      list = list.sort((a, b) => {
        const numA = eseguitiMap.get(a.id_canti) || 0;
        const numB = eseguitiMap.get(b.id_canti) || 0;
        return numB - numA;
      });
    } else if (suggeriti) {
      const suggMap = this.cantiLettureService.suggestionsMap();
      list = list.sort((a, b) => {
        const pesoA = suggMap.get(a.id_canti) || 0;
        const pesoB = suggMap.get(b.id_canti) || 0;
        return pesoB - pesoA;
      });
    }

    return list;
  });
  
  public visibleCanti = computed(() => {
    if (this.playlistService.selectionMode() && !this.isAddingSongs()) {
      return this.filteredCanti();
    }
    return this.filteredCanti().slice(0, this.limit());
  });

  constructor() {
    // Check if there is an update available
    this.checkUpdateStatus();
    if (this.swUpdate.isEnabled) {
      this.swUpdate.versionUpdates.subscribe(evt => {
        if (evt.type === 'VERSION_READY') {
          this.hasUpdateAvailable.set(true);
        }
      });
    }

    // Polling setup: check for updates every 30 seconds
    this.updatePollInterval = setInterval(() => {
      this.checkUpdateStatus();
    }, 30000);



    // Track initial community filter state to avoid clearing during the initial run of the effect
    let prevFilterActive = this.comunitaService.isFilterActive();
    let prevComunitaCode = this.comunitaService.comunitaCode();

    // Automatically reset all other filters and active playlist when toggling the community filter or changing community
    effect(() => {
      const active = this.comunitaService.isFilterActive();
      const code = this.comunitaService.comunitaCode();
      
      if (active !== prevFilterActive || code !== prevComunitaCode) {
        prevFilterActive = active;
        prevComunitaCode = code;

        this.selectedLiturgico.set(null);
        this.selectedTematico.set(null);
        this.showOnlyMine.set(false);
        this.showTopTen.set(false);
        this.showSuggeriti.set(false);
        this.showValidati.set(false);
        this.showNonValidati.set(false);
        this.playlistService.activeListIds.set([]);
        this.playlistService.activeListName.set(null);
        this.playlistService.activePlaylistId.set(null);
        this.searchQuery.set('');
        this.activeFilterType.set(null);
        this.limit.set(10);
      }
    }, { allowSignalWrites: true });

    // Sync speech recognition results to search query
    effect(() => {
      const transcript = this.audioEngine.searchTranscript();
      if (transcript) {
        this.searchQuery.set(transcript);
      }
    });

    let queryParamsSubscribed = false;
    effect(() => {
      if (this.settingsService.isVersionCheckComplete() && !queryParamsSubscribed) {
        queryParamsSubscribed = true;
        this.queryParamsSubscription = this.route.queryParams.subscribe(params => {
          if (params['id']) {
            const idVal = params['id'];
            this.router.navigate([], { queryParams: { id: null, t: null }, queryParamsHandling: 'merge', replaceUrl: true }).then(() => {
              this.goToCanto(idVal);
            });
          }
          if (params['import']) {
            this.handleImport(params['import']);
          }
          if (params['import-canto']) {
            this.handleImportCanto(params['import-canto']);
          }
          if (params['song-uid'] && params['song-id']) {
            this.handleRemoteSongImport(params['song-uid'], params['song-id']);
          }
          if (params['playlist-uid']) {
            this.handleRemotePlaylistImport(params['playlist-uid'], params['playlist-id']);
          }
          if (params['restore-uid']) {
            this.handleRemoteRestore(params['restore-uid']);
          }
        });
      }
    }, { allowSignalWrites: true });

    let hasAutoActivatedPlaylist = false;
    effect(() => {
      const lastPl = this.playlistService.lastPlaylist();
      const versionReady = this.settingsService.isVersionCheckComplete();
      
      if (versionReady && lastPl && !hasAutoActivatedPlaylist) {
        const params = this.route.snapshot.queryParams;
        if (!params['id'] && !params['import'] && !params['playlist-uid'] && !params['restore-uid'] && !params['song-uid'] && !params['import-canto']) {
          hasAutoActivatedPlaylist = true;
          this.selectPlaylist(lastPl);
          this.activeFilterType.set('playlist');
          if (lastPl.ids && lastPl.ids.length > 0) {
            this.goToCanto(lastPl.ids[0]);
          }
        } else {
          hasAutoActivatedPlaylist = true;
        }
      }
    }, { allowSignalWrites: true });

    let prevSelectionMode = false;

    effect(() => {
      const selectionMode = this.playlistService.selectionMode();
      const selectedIds = this.playlistService.selectedIds();
      const activeIds = this.playlistService.activeListIds();

      if (selectionMode) {
        if (!prevSelectionMode) {
          if (activeIds.length === 0 || this.playlistService.activePlaylistId() === null) {
            this.isAddingSongs.set(true);
          } else {
            this.isAddingSongs.set(false);
          }
        }
        prevSelectionMode = true;

        const currentIds = this.reorderList().map(c => c.id);
        const newIds = Array.from(selectedIds);
        
        // Use a set of IDs for faster lookup
        const currentIdSet = new Set(currentIds);
        const newIdSet = new Set(newIds);

        // Check if there are differences in the SET of IDs
        const added = newIds.filter(id => !currentIdSet.has(id));
        const removed = currentIds.filter(id => !newIdSet.has(id));

        if (added.length > 0 || removed.length > 0) {
          let updatedList = [...this.reorderList()];
          
          // Remove songs no longer selected
          if (removed.length > 0) {
            updatedList = updatedList.filter(c => newIdSet.has(c.id));
          }
          
          // Add newly selected songs at the end
          if (added.length > 0) {
            const newSongs = added.map(id => this.findCanto(id)).filter((c): c is any => !!c);
            updatedList = [...updatedList, ...newSongs];
          }
          
          // Previeni cicli infiniti se il contenuto della lista non è effettivamente cambiato
          const currentIdsStr = currentIds.join(',');
          const updatedIdsStr = updatedList.map(c => c.id).join(',');
          if (currentIdsStr !== updatedIdsStr) {
            this.reorderList.set(updatedList);
          }
        }
      } else {
        prevSelectionMode = false;
        this.isAddingSongs.set(false);
      }
    }, { allowSignalWrites: true });
  }



  async handleImport(base64: string) {
    try {
      const base64Safe = base64.replace(/ /g, '+');
      const decoded = decodeURIComponent(escape(atob(base64Safe)));
      const json = JSON.parse(decoded);

      if (json && json.comunitaCode) {
        // 1. Abilita la funzionalità comunità nelle impostazioni
        this.settingsService.comunitaEnabled.set(true);
        localStorage.setItem('comunita-enabled', 'true');

        // 2. Mostra un overlay di caricamento premium con indicatore di progresso
        const loading = await this.loadingCtrl.create({
          message: 'Attivazione comunità: Caricamento 0%',
          cssClass: 'premium-loading',
          spinner: 'crescent'
        });
        await loading.present();

        // Iscrizione agli aggiornamenti di progresso
        let progressInterval: any = null;
        progressInterval = setInterval(() => {
          const pct = this.comunitaService.loadingProgress();
          loading.message = `Attivazione comunità: Caricamento ${pct}%`;
          if (pct >= 100) {
            clearInterval(progressInterval);
          }
        }, 100);

        const success = await this.comunitaService.setComunitaCode(json.comunitaCode);
        clearInterval(progressInterval);
        await loading.dismiss();

        if (success) {
          const toast = await this.toastCtrl.create({
            message: `Comunità attivata: ${this.comunitaService.comunitaNome()}`,
            duration: 2500,
            color: 'success',
            position: 'bottom'
          });
          await toast.present();
        } else {
          const toast = await this.toastCtrl.create({
            message: 'Codice comunità non trovato o errore di connessione.',
            duration: 3000,
            color: 'danger',
            position: 'bottom'
          });
          await toast.present();
        }
      }

      const openFirst = this.route.snapshot.queryParams['openFirst'] === '1';
      if (this.playlistService.processImportJson(json)) {
        this.limit.set(50); // Mostra più canti inizialmente per le playlist speciali
        this.activeFilterType.set('playlist');
        await this.router.navigate([], { queryParams: { import: null, openFirst: null }, queryParamsHandling: 'merge', replaceUrl: true });
        if (openFirst && json.ids && json.ids.length > 0) {
          this.goToCanto(json.ids[0]);
        }
      }
    } catch (e) {
      console.error('Failed to import playlist', e);
      const toast = await this.toastCtrl.create({
        message: 'Errore durante l\'importazione della playlist.',
        duration: 3000,
        color: 'danger',
        position: 'bottom'
      });
      await toast.present();
    }
  }

  async handleImportCanto(base64: string) {
    try {
      const base64Safe = base64.replace(/ /g, '+');
      const decoded = decodeURIComponent(escape(atob(base64Safe)));
      const json = JSON.parse(decoded);

      if (json && json.cantoShare && json.titolo) {
        const id_canti = Date.now();
        const id = `remote_share_${id_canti}`;
        
        const canto: any = {
          id: id,
          id_canti: id_canti,
          titolo: json.titolo,
          autore: json.autore || '',
          testo: json.testo || '',
          accordi: json.accordi || '',
          link_youtube: json.link_youtube || '',
          id_momenti: json.id_momenti || [],
          nonValidato: true
        };

        await this.playlistService.saveRemoteShareCanto(canto);

        const toast = await this.toastCtrl.create({
          message: `Canto "${canto.titolo}" importato nei brani remoti non validati!`,
          duration: 3000,
          color: 'success',
          position: 'bottom'
        });
        await toast.present();

        await this.router.navigate([], { queryParams: { 'import-canto': null }, queryParamsHandling: 'merge', replaceUrl: true });
        this.goToCanto(canto.id);
      }
    } catch (e) {
      console.error('Failed to import canto', e);
      const toast = await this.toastCtrl.create({
        message: 'Errore durante l\'importazione del canto.',
        duration: 3000,
        color: 'danger',
        position: 'bottom'
      });
      await toast.present();
    }
  }

  async handleRemoteSongImport(uid: string, songId: string) {
    const loading = await this.loadingCtrl.create({
      message: 'Scaricamento canto da remoto...'
    });
    await loading.present();

    try {
      const response = await fetch(`https://api.canticristiani.it/${uid}.json?cb=${Date.now()}`, { cache: 'no-store' });
      if (!response.ok) {
        throw new Error(`Risposta del server non valida: ${response.status}`);
      }
      const remoteJson = await response.json();
      if (Array.isArray(remoteJson)) {
        const item = remoteJson.find((x: any) => 
          Number(x.id_canti) === Number(songId) && 
          (!x.momenti || (!x.momenti.includes('Playlist') && !x.momenti.includes('UserMetadata')))
        );

        if (!item) {
          throw new Error('Canto non trovato nel profilo remoto.');
        }

        const id = `remote_share_${item.id_canti}`;
        const canto: any = {
          id: id,
          id_canti: Number(item.id_canti),
          titolo: item.titolo || 'Senza Titolo',
          autore: item.autore || '',
          testo: item.testo || '',
          accordi: item.accordi || (item.testo?.includes('[') ? item.testo : undefined),
          link_youtube: item.link_youtube || '',
          id_momenti: item.momenti?.map((m: any) => Number(m)).filter((m: any) => !isNaN(m)) || [],
          nonValidato: true
        };

        await this.playlistService.saveRemoteShareCanto(canto);

        const toast = await this.toastCtrl.create({
          message: `Canto "${canto.titolo}" importato nei brani remoti non validati!`,
          duration: 3000,
          color: 'success',
          position: 'bottom'
        });
        await toast.present();

        await this.router.navigate([], { queryParams: { 'song-uid': null, 'song-id': null }, queryParamsHandling: 'merge', replaceUrl: true });
        this.goToCanto(canto.id);
      } else {
        throw new Error('Formato dati non valido.');
      }
    } catch (err: any) {
      console.error('Failed to import remote song:', err);
      const alert = await this.alertCtrl.create({
        header: 'Errore Importazione',
        message: 'Impossibile scaricare il canto da remoto. Controlla la connessione o il link.',
        buttons: ['OK']
      });
      await alert.present();
      await this.router.navigate([], { queryParams: { 'song-uid': null, 'song-id': null }, queryParamsHandling: 'merge', replaceUrl: true });
    } finally {
      await loading.dismiss();
    }
  }

  async handleRemotePlaylistImport(uid: string, pid?: string) {
    const loading = await this.loadingCtrl.create({
      message: 'Scaricamento playlist da remoto...'
    });
    await loading.present();

    let hasNavigatedToCanto = false;
    const openFirst = this.route.snapshot.queryParams['openFirst'] === '1';
    try {
      const response = await fetch(`https://api.canticristiani.it/${uid}.json?cb=${Date.now()}`, { cache: 'no-store' });
      if (!response.ok) {
        throw new Error(`Risposta del server non valida: ${response.status}`);
      }
      const remoteJson = await response.json();
      if (Array.isArray(remoteJson)) {
        // 1. Reconstruct custom songs
        const customSongs = remoteJson
          .filter((item: any) => item.momenti && !item.momenti.includes('Playlist'))
          .map((item: any) => ({
            id: `my_${item.id_canti}`,
            id_canti: Number(item.id_canti),
            titolo: item.titolo,
            testo: item.testo,
            accordi: item.accordi || (item.testo?.includes('[') ? item.testo : undefined),
            autore: item.autore || '',
            link_youtube: item.link_youtube || '',
            id_momenti: item.momenti?.map((m: any) => Number(m)).filter((m: any) => !isNaN(m)) || []
          }));

        // 2. Reconstruct playlists
        const playlists = remoteJson
          .filter((item: any) => item.momenti && item.momenti.includes('Playlist'))
          .map((item: any) => {
            let songSettings = {};
            if (item.periodi && item.periodi.length > 0) {
              try {
                songSettings = JSON.parse(item.periodi[0]);
              } catch (e) {}
            }
            return {
              id: `remote_${uid}_${item.id_canti}`,
              name: `[Remote] ${item.titolo}`,
              ids: item.testo ? item.testo.split(',') : [],
              songSettings: songSettings,
              createdAt: new Date(),
              isRemote: true
            };
          });

        if (playlists.length === 0) {
          throw new Error('Nessuna playlist trovata in questa identità.');
        }

        // Find the selected one
        let selectedPl = playlists[0];
        if (pid) {
          const targetId = `remote_${uid}_${pid}`;
          const found = playlists.find(p => p.id === targetId || p.id.endsWith(`_${pid}`));
          if (found) {
            selectedPl = found;
          }
        }

        await this.playlistService.saveRemotePlaylist(selectedPl, customSongs);

        // Clear other filters to avoid confusion
        this.selectedLiturgico.set(null);
        this.selectedTematico.set(null);

        // Select it immediately
        this.selectPlaylist(selectedPl);
        this.activeFilterType.set('playlist');
        
        await loading.dismiss();

        const toast = await this.toastCtrl.create({
          message: `Playlist "${selectedPl.name}" caricata per consultazione!`,
          duration: 3000,
          color: 'success'
        });
        await toast.present();

        if (selectedPl.ids && selectedPl.ids.length > 0) {
          hasNavigatedToCanto = true;
          await this.router.navigate([], { queryParams: { 'playlist-uid': null, 'playlist-id': null, 'openFirst': null }, queryParamsHandling: 'merge', replaceUrl: true });
          if (openFirst) {
            this.goToCanto(selectedPl.ids[0]);
          }
        }
      } else {
        throw new Error('Formato dati non valido.');
      }
    } catch (err: any) {
      await loading.dismiss();
      console.error('Failed to import remote playlist:', err);
      const alert = await this.alertCtrl.create({
        header: 'Errore Importazione',
        message: 'Impossibile scaricare la playlist da remoto. Controlla la connessione o il codice.',
        buttons: ['OK']
      });
      await alert.present();
    } finally {
      if (!hasNavigatedToCanto) {
        this.router.navigate([], { queryParams: { 'playlist-uid': null, 'playlist-id': null, 'openFirst': null }, queryParamsHandling: 'merge', replaceUrl: true });
      }
    }
  }

  async handleRemoteRestore(uid: string) {
    const alert = await this.alertCtrl.create({
      header: 'Ripristina Identità',
      message: 'Sei sicuro di voler scaricare e ripristinare i dati di questa identità? L\'ID attuale del dispositivo verrà sovrascritto.',
      buttons: [
        { text: 'Annulla', role: 'cancel' },
        {
          text: 'Ripristina',
          role: 'destructive',
          handler: async () => {
            const loading = await this.loadingCtrl.create({
              message: 'Scaricamento dati da remoto...'
            });
            await loading.present();

            try {
              const response = await fetch(`https://api.canticristiani.it/${uid}.json?cb=${Date.now()}`, { cache: 'no-store' });
              if (response.ok) {
                const remoteJson = await response.json();
                if (Array.isArray(remoteJson)) {
                  // Reconstruct user name/metadata
                  const userMetadata = remoteJson.find((item: any) => item.momenti && item.momenti.includes('UserMetadata'));
                  if (userMetadata && userMetadata.titolo) {
                    this.settingsService.setUserName(userMetadata.titolo);
                  }

                  // Reconstruct custom songs
                  const customSongs = remoteJson
                    .filter((item: any) => (!item.momenti || !item.momenti.includes('Playlist')) && (!item.momenti || !item.momenti.includes('UserMetadata')))
                    .map((item: any) => ({
                      id: `my_${item.id_canti}`,
                      id_canti: Number(item.id_canti),
                      titolo: item.titolo || 'Senza Titolo',
                      testo: item.testo || '',
                      accordi: item.accordi || (item.testo?.includes('[') ? item.testo : undefined),
                      autore: item.autore || '',
                      link_youtube: item.link_youtube || '',
                      id_momenti: item.momenti?.map((m: any) => Number(m)).filter((m: any) => !isNaN(m)) || []
                    }));

                  if (customSongs.length > 0) {
                    this.myCantiService.myCanti.set(customSongs);
                    const storage = this.cantiService.getStorage();
                    if (storage) {
                      await storage.set('my-canti', customSongs);
                    }
                  }

                  // Reconstruct playlists
                  const playlists = remoteJson
                    .filter((item: any) => item.momenti && item.momenti.includes('Playlist'))
                    .map((item: any) => {
                      let songSettings = {};
                      if (item.periodi && item.periodi.length > 0) {
                        try {
                          songSettings = JSON.parse(item.periodi[0]);
                        } catch (e) {}
                      }
                      return {
                        id: String(item.id_canti),
                        name: item.titolo,
                        ids: item.testo ? item.testo.split(',') : [],
                        songSettings: songSettings,
                        createdAt: new Date()
                      };
                    });

                  if (playlists.length > 0) {
                    this.playlistService.playlists.set(playlists);
                    if (this.playlistService['_storage']) {
                      const key = this.playlistService.getPlaylistsStorageKey();
                      await this.playlistService['_storage'].set(key, playlists);
                    }
                  }
                }
              }
            } catch (err) {
              console.error('Failed to restore remote backup:', err);
            } finally {
              await loading.dismiss();
            }

             this.settingsService.setUserUuid(uid);
            
            const toast = await this.toastCtrl.create({
              message: 'Dati ripristinati con successo! Ricaricamento...',
              duration: 2000,
              color: 'success'
            });
            await toast.present();

            setTimeout(() => {
              window.location.replace(window.location.origin + window.location.pathname);
            }, 1500);
          }
        }
      ]
    });
    await alert.present();
  }

  ionViewWillLeave() {
  }

  ngOnDestroy() {
    this.audioEngine.stopSearchRecognition();
    if (this.updatePollInterval) {
      clearInterval(this.updatePollInterval);
    }
    if (this.queryParamsSubscription) {
      this.queryParamsSubscription.unsubscribe();
    }
  }

  onSearch(event: any) {
    this.searchQuery.set(event.detail.value);
    this.limit.set(30);
  }

  async deleteMyCanto(id: string, event: Event) {
    event.stopPropagation();
    const alert = await this.alertCtrl.create({
      header: 'Elimina Canto',
      message: 'Sei sicuro di voler eliminare questo canto dai tuoi brani personali?',
      buttons: [
        { text: 'Annulla', role: 'cancel' },
        { 
          text: 'Elimina', 
          role: 'destructive',
          handler: () => {
            this.myCantiService.deleteCanto(id);
          }
        }
      ]
    });
    await alert.present();
  }

  findCanto(id: string) {
    if (this.comunitaService.comunitaCode() && this.comunitaService.isFilterActive()) {
      const personal = this.comunitaService.comunitaCantiPersonali().find(c => c.id === id);
      if (personal) return personal;
    }
    return [
      ...this.cantiService.canti(),
      ...this.myCantiService.myCanti(),
      ...this.playlistService.remoteCustomSongs(),
      ...this.playlistService.remoteShareCanti(),
      ...this.comunitaService.comunitaCantiPersonali()
    ].find(c => c.id === id || String(c.id_canti) === id);
  }

  getPlayingCanto() {
    const id = this.youtubePlayerService.currentCantoId();
    if (!id) return null;
    return this.findCanto(id);
  }

  goToCanto(id: string) {
    const params: any = { id };
    const isPlaying = this.youtubePlayerService.isPlaying();

    if (this.youtubePlayerService.currentCantoId() === id && isPlaying) {
      params.t = Math.floor(this.youtubePlayerService.videoProgress());
    }
    
    this.playlistService.autoPlayPlaylist.set(isPlaying);
    this.router.navigate(['/player'], { queryParams: params });
  }

  toggleOnlyMine() {
    this.showOnlyMine.update(v => !v);
    this.activeFilterType.set(null);
    this.limit.set(10);
  }

  clearOnlyMine(event: Event) {
    event.stopPropagation();
    this.showOnlyMine.set(false);
    this.limit.set(10);
  }

  toggleIndex(id: number, type: 'liturgico' | 'tematico' | 'playlist' | 'lista_completa') {
    if (type === 'liturgico') {
      this.selectedLiturgico.update(cur => cur === id ? null : id);
    } else if (type === 'tematico') {
      this.selectedTematico.update(cur => cur === id ? null : id);
    }
    
    // Mantieni aperto il menu di secondo livello se c'è una selezione attiva per quel tipo
    let hasSelection = false;
    if (type === 'liturgico' && this.selectedLiturgico() !== null) {
      hasSelection = true;
    } else if (type === 'tematico' && this.selectedTematico() !== null) {
      hasSelection = true;
    }
    
    if (!hasSelection) {
      this.activeFilterType.set(null);
    }
    this.limit.set(10);
  }

  clearLiturgico(event: Event) {
    event.stopPropagation();
    this.selectedLiturgico.set(null);
    this.activeFilterType.set(null);
    this.limit.set(10);
  }

  clearTematico(event: Event) {
    event.stopPropagation();
    this.selectedTematico.set(null);
    this.activeFilterType.set(null);
    this.limit.set(10);
  }

  isIndexSelected(id: number): boolean {
    return this.selectedLiturgico() === id || this.selectedTematico() === id;
  }

  clearFilters() {
    const type = this.activeFilterType();
    
    if (this.playlistService.activeListIds().length > 0) {
      this.clearSpecialList();
    }

    if (type === 'liturgico') {
      if (this.selectedLiturgico() === null) {
        this.selectedTematico.set(null);
      } else {
        this.selectedLiturgico.set(null);
      }
    } else if (type === 'tematico') {
      if (this.selectedTematico() === null) {
        this.selectedLiturgico.set(null);
      } else {
        this.selectedTematico.set(null);
      }
    } else {
      this.selectedLiturgico.set(null);
      this.selectedTematico.set(null);
    }
    
    this.showOnlyMine.set(false);
    this.searchQuery.set('');
    this.audioEngine.clearSearchTranscript();
  }

  activeFiltersCount(): number {
    let count = 0;
    if (this.selectedLiturgico() !== null) count++;
    if (this.selectedTematico() !== null) count++;
    return count;
  }

  getSelectedLiturgicoLabel(): string | null {
    const id = this.selectedLiturgico();
    if (id === null) return null;
    return this.cantiService.indiceLiturgico().find(m => m.id === id)?.tag_name || null;
  }

  getSelectedTematicoLabel(): string | null {
    const id = this.selectedTematico();
    if (id === null) return null;
    return this.cantiService.indiceTematico().find(m => m.id === id)?.tag_name || null;
  }

  hasActiveFilters(): boolean {
    return this.selectedLiturgico() !== null || 
           this.selectedTematico() !== null || 
           this.showOnlyMine() || 
           this.showTopTen() ||
           this.showSuggeriti() ||
           this.showValidati() ||
           this.showNonValidati() ||
           this.playlistService.activeListName() !== null ||
           this.searchQuery() !== '';
  }

  shouldShowSubSectionToolbar(): boolean {
    if (this.playlistService.selectionMode() && this.reorderList().length > 0) {
      return true;
    }
    const filterType = this.activeFilterType();
    if (filterType) {
      return true;
    }
    return false;
  }

  clearAllFilters() {
    this.selectedLiturgico.set(null);
    this.selectedTematico.set(null);
    this.showOnlyMine.set(false);
    this.showTopTen.set(false);
    this.showSuggeriti.set(false);
    this.showValidati.set(false);
    this.showNonValidati.set(false);
    this.playlistService.activeListIds.set([]);
    this.playlistService.activeListName.set(null);
    this.playlistService.activePlaylistId.set(null);
    this.searchQuery.set('');
    this.activeFilterType.set(null);
    this.limit.set(10);
  }

  toggleFilterType(type: 'liturgico' | 'tematico' | 'playlist' | 'lista_completa') {
    if (this.activeFilterType() === type) {
      // Chiudi solo se non ci sono selezioni di secondo livello attive per questo tipo
      let hasSelection = false;
      if (type === 'liturgico' && this.selectedLiturgico() !== null) {
        hasSelection = true;
      } else if (type === 'tematico' && this.selectedTematico() !== null) {
        hasSelection = true;
      } else if (type === 'playlist' && this.playlistService.activePlaylistId() !== null) {
        hasSelection = true;
      } else if (type === 'lista_completa' && (this.showValidati() || this.showNonValidati())) {
        hasSelection = true;
      }
      
      if (!hasSelection) {
        this.activeFilterType.set(null);
      }
    } else {
      this.activeFilterType.set(type);
    }
  }

  selectPlaylist(pl: any) {
    this.playlistService.activeListIds.set(pl.ids);
    this.playlistService.activeListName.set(pl.name);
    this.playlistService.activePlaylistId.set(pl.id);
    // Mantieni il menu aperto poiché la playlist è ora selezionata ed attiva
    this.limit.set(50);
  }

  toggleTopTen() {
    this.showTopTen.update(v => !v);
    this.activeFilterType.set(null);
    this.limit.set(30);
  }

  clearTopTen(event?: Event) {
    if (event) event.stopPropagation();
    this.showTopTen.set(false);
    this.limit.set(30);
  }

  toggleValidati() {
    this.showValidati.update(v => !v);
    this.showNonValidati.set(false);
    if (!this.showValidati()) {
      this.activeFilterType.set(null);
    } else {
      this.activeFilterType.set('lista_completa');
    }
    this.limit.set(30);
  }

  clearValidati(event?: Event) {
    if (event) event.stopPropagation();
    this.showValidati.set(false);
    this.activeFilterType.set(null);
    this.limit.set(30);
  }

  toggleNonValidati() {
    this.showNonValidati.update(v => !v);
    this.showValidati.set(false);
    if (!this.showNonValidati()) {
      this.activeFilterType.set(null);
    } else {
      this.activeFilterType.set('lista_completa');
    }
    this.limit.set(30);
  }

  clearNonValidati(event?: Event) {
    if (event) event.stopPropagation();
    this.showNonValidati.set(false);
    this.activeFilterType.set(null);
    this.limit.set(30);
  }

  clearListaCompleta(event?: Event) {
    if (event) event.stopPropagation();
    this.showValidati.set(false);
    this.showNonValidati.set(false);
    this.activeFilterType.set(null);
    this.limit.set(10);
  }

  toggleSuggeriti() {
    this.showSuggeriti.update(v => !v);
    if (this.showSuggeriti()) {
      this.isMassCardExpanded.set(true);
    }
    this.activeFilterType.set(null);
    this.limit.set(30);
  }

  clearSuggeriti(event?: Event) {
    if (event) event.stopPropagation();
    this.showSuggeriti.set(false);
    this.limit.set(30);
  }

  getMassSuggestionWeight(id_canti: number): number | null {
    const weight = this.cantiLettureService.suggestionsMap().get(id_canti);
    return weight !== undefined ? weight : null;
  }

  getMassSuggestionMoment(id_canti: number): string | null {
    const moments = this.cantiLettureService.suggestionsMomentsMap().get(id_canti);
    return moments && moments.length > 0 ? moments.join(', ') : null;
  }

  getSelectedMassFormattedDate(): string | null {
    const dateStr = this.cantiLettureService.selectedMassDate();
    if (!dateStr) return null;
    const parts = dateStr.split('-');
    if (parts.length === 3) {
      return `${parts[2]}/${parts[1]}/${parts[0]}`;
    }
    return dateStr;
  }

  getSelectedMassTitle(): string | null {
    const dateStr = this.cantiLettureService.selectedMassDate();
    const data = this.cantiLettureService.data();
    if (dateStr && data && data.masses[dateStr]) {
      return data.masses[dateStr].title;
    }
    return null;
  }

  getSelectedMassSummary(): string | null {
    const dateStr = this.cantiLettureService.selectedMassDate();
    const data = this.cantiLettureService.data();
    if (dateStr && data && data.masses[dateStr]) {
      return data.masses[dateStr].summary || null;
    }
    return null;
  }

  getEsecuzioniCount(id: string): number | null {
    const numId = parseInt(id, 10);
    if (isNaN(numId)) return null;
    const es = this.cantiService.cantiEseguiti().find(x => x.id_canti === numId);
    return es ? es.num : 0;
  }

  onImgLoad(id: string) {
    this.loadedThumbs.add(id);
  }

  openYoutube(event: Event, link: string) {
    event.stopPropagation();
    const videoId = this.cantiService.getYoutubeId(link);
    if (videoId) {
      window.open(`https://www.youtube.com/watch?v=${videoId}`, '_blank');
    }
  }

  playVideo(event: Event, id: string) {
    event.stopPropagation();
    if (!this.youtubePlayerService.isPlayerSupported()) {
      return;
    }
    this.youtubePlayerService.setMediaSessionCallbacks(
      () => this.playNextPreview(),
      () => this.playPrevPreview()
    );
    this.youtubePlayerService.initPlayer(
      id, 
      0, 
      () => {
        if (this.settingsService.autoAdvance()) {
          this.playNextPreview();
        } else {
          this.youtubePlayerService.stop();
        }
      }, 
      () => {
        if (this.settingsService.autoAdvance()) {
          setTimeout(() => this.playNextPreview(), 500);
        } else {
          this.youtubePlayerService.stop();
        }
      }
    );
  }

  stopVideo(event: Event) {
    if (event) event.stopPropagation();
    this.youtubePlayerService.stop();
    this.playlistService.autoPlayPlaylist.set(false);
  }

  playNextPreview(event?: Event) {
    if (event) event.stopPropagation();
    const currentId = this.youtubePlayerService.currentCantoId();
    if (!currentId) return;

    const list = this.visibleCanti();
    const currentIndex = list.findIndex(c => c.id === currentId);
    
    for (let i = currentIndex + 1; i < list.length; i++) {
      if (list[i].link_youtube) {
        this.playVideo(new Event('skip'), list[i].id);
        
        setTimeout(() => {
          const el = document.getElementById('canto-' + list[i].id);
          if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });
        }, 300);
        return;
      }
    }
    
    this.youtubePlayerService.stop();
  }

  playPrevPreview(event?: Event) {
    if (event) event.stopPropagation();
    const currentId = this.youtubePlayerService.currentCantoId();
    if (!currentId) return;

    const list = this.visibleCanti();
    const currentIndex = list.findIndex(c => c.id === currentId);
    
    for (let i = currentIndex - 1; i >= 0; i--) {
      if (list[i].link_youtube) {
        this.playVideo(new Event('skip'), list[i].id);
        
        setTimeout(() => {
          const el = document.getElementById('canto-' + list[i].id);
          if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });
        }, 300);
        return;
      }
    }
  }

  onSeek(event: any) {
    this.youtubePlayerService.seekTo(event.detail.value);
  }

  onSeekStart() {
    this.isSeeking = true;
  }

  onSeekEnd() {
    this.isSeeking = false;
  }

  getMomentiForCanto(ids: number[] | undefined): any[] {
    if (!ids) return [];
    return this.cantiService.momenti()
      .filter(m => ids.includes(m.id));
  }

  filterByMomento(event: Event, id: number) {
    event.stopPropagation();
    // Use liturgico as default for momento tags
    this.toggleIndex(id, 'liturgico');
    // Scroll to top to show results
    const content = document.querySelector('ion-content');
    if (content) (content as any).scrollToTop(300);
  }

  loadData(event: any) {
    setTimeout(() => {
      this.limit.update(l => l + 10);
      event.target.complete();
    }, 500);
  }

  // --- Touch Gestures for Pinch-to-Zoom ---
  onTouchStart(event: TouchEvent) {
    if (event.touches.length === 2) {
      this.initialPinchDistance = this.getDistance(event.touches[0], event.touches[1]);
      this.initialFontSize = this.fontSize();
    }
  }

  onTouchMove(event: TouchEvent) {
    if (event.touches.length === 2 && this.initialPinchDistance !== null) {
      // We don't preventDefault here to allow scrolling if needed, 
      // but usually pinch should be captured.
      const currentDistance = this.getDistance(event.touches[0], event.touches[1]);
      const ratio = currentDistance / this.initialPinchDistance;
      let newSize = this.initialFontSize * ratio;
      
      // Clamp values
      newSize = Math.max(this.MIN_FONT, Math.min(this.MAX_FONT, newSize));
      
      if (Math.abs(newSize - this.fontSize()) > 0.01) {
        this.fontSize.set(newSize);
      }
    }
  }

  onTouchEnd() {
    this.initialPinchDistance = null;
  }

  private getDistance(t1: Touch, t2: Touch): number {
    return Math.sqrt(Math.pow(t1.clientX - t2.clientX, 2) + Math.pow(t1.clientY - t2.clientY, 2));
  }

  handleScannedData(data: string) {
    if (!data) return;

    if (data.includes('playlist-uid=')) {
      try {
        const urlObj = new URL(data);
        const uid = urlObj.searchParams.get('playlist-uid');
        const pid = urlObj.searchParams.get('playlist-id');
        if (uid) {
          this.handleRemotePlaylistImport(uid, pid || undefined);
          return;
        }
      } catch (e) {
        const uidMatch = data.match(/[?&]playlist-uid=([^&]+)/);
        const pidMatch = data.match(/[?&]playlist-id=([^&]+)/);
        if (uidMatch && uidMatch[1]) {
          this.handleRemotePlaylistImport(uidMatch[1], pidMatch ? pidMatch[1] : undefined);
          return;
        }
      }
    }

    if (data.includes('restore-uid=')) {
      try {
        const urlObj = new URL(data);
        const uid = urlObj.searchParams.get('restore-uid');
        if (uid) {
          this.handleRemoteRestore(uid);
          return;
        }
      } catch (e) {
        const uidMatch = data.match(/[?&]restore-uid=([^&]+)/);
        if (uidMatch && uidMatch[1]) {
          this.handleRemoteRestore(uidMatch[1]);
          return;
        }
      }
    }

    if (data.includes('import-canto=')) {
      try {
        let base64 = '';
        if (data.includes('?import-canto=')) {
          base64 = data.split('?import-canto=')[1];
        } else if (data.includes('&import-canto=')) {
          base64 = data.split('&import-canto=')[1];
        }

        if (base64.includes('&')) {
          base64 = base64.split('&')[0];
        }
        if (base64.includes('#')) {
          base64 = base64.split('#')[0];
        }

        this.handleImportCanto(base64);
        return;
      } catch (e) {
        console.error('Failed to parse scanned canto link', e);
      }
    }

    if (data.includes('import=')) {
      try {
        let base64 = '';
        if (data.includes('?import=')) {
          base64 = data.split('?import=')[1];
        } else if (data.includes('&import=')) {
          base64 = data.split('&import=')[1];
        }

        if (base64.includes('&')) {
          base64 = base64.split('&')[0];
        }
        if (base64.includes('#')) {
          base64 = base64.split('#')[0];
        }

        this.handleImport(base64);
        return;
      } catch (e) {
        console.error('Failed to parse scanned link', e);
      }
    }

    if (data.startsWith('canti:')) {
      const parts = data.replace('canti:', '').split(':');
      let idsStr = '';
      let playlistName = 'Lista Parrocchiale';
      if (parts.length > 1) {
        playlistName = parts[0];
        idsStr = parts[1];
      } else {
        idsStr = parts[0];
      }
      
      const ids = idsStr.split(',').map(id => id.trim());
      this.playlistService.activeListIds.set(ids);
      this.playlistService.activeListName.set(playlistName);
      this.limit.set(50); // Show more initially for special lists
      
      // Clear other filters to avoid confusion
      this.selectedLiturgico.set(null);
      this.selectedTematico.set(null);

      // Automatically save to the device!
      this.playlistService.savePlaylist(playlistName, ids);

      // Activate the playlist filter and open the first song!
      this.activeFilterType.set('playlist');
      if (ids.length > 0) {
        this.goToCanto(ids[0]);
      }
    }
  }

  toggleVoiceSearch() {
    if (this.audioEngine.isSearching()) {
      this.audioEngine.stopSearchRecognition();
    } else {
      this.audioEngine.startSearchRecognition();
    }
  }

  async finishSelection() {
    const alert = await this.alertCtrl.create({
      header: 'Salva Playlist',
      inputs: [
        {
          name: 'name',
          type: 'text',
          placeholder: 'Nome della playlist',
          value: this.playlistService.activeListName() || ''
        }
      ],
      buttons: [
        {
          text: 'Annulla',
          role: 'cancel'
        },
        {
          text: 'Salva',
          handler: async (data) => {
            if (data.name) {
              const ids = this.reorderList().map(s => s.id);
              const activeId = this.playlistService.activePlaylistId();
              const pl = activeId ? this.playlistService.playlists().find(p => p.id === activeId) : null;
              const songSettings = pl ? pl.songSettings : undefined;
              await this.playlistService.savePlaylist(data.name, ids, songSettings);
              
              const toast = await this.toastCtrl.create({
                message: 'Playlist salvata!',
                duration: 2000,
                color: 'success'
              });
              await toast.present();
              
              this.isAddingSongs.set(false);
              this.playlistService.selectionMode.set(false);
              this.playlistService.selectedIds.set(new Set());
              return true;
            }
            return false;
          }
        }
      ]
    });
    await alert.present();
  }

  cancelSelection() {
    const id = this.playlistService.activePlaylistId();
    if (id) {
      const pl = this.playlistService.playlists().find(p => p.id === id);
      if (pl) {
        this.playlistService.activeListIds.set(pl.ids);
        this.playlistService.activeListName.set(pl.name);
      }
    }
    
    this.playlistService.selectionMode.set(false);
    this.playlistService.selectedIds.set(new Set());
    this.isAddingSongs.set(false);
  }

  isComunitaPlaylist(): boolean {
    const id = this.playlistService.activePlaylistId();
    return !!id && id.startsWith('comunita_');
  }

  isRemotePlaylist(): boolean {
    const id = this.playlistService.activePlaylistId();
    return !!id && id.startsWith('remote_');
  }

  isActivePlaylistSaved(): boolean {
    const id = this.playlistService.activePlaylistId();
    if (!id) return false;
    return this.playlistService.playlists().some(p => p.id === id);
  }

  clearSpecialList(event?: Event) {
    if (event) event.stopPropagation();
    this.playlistService.activeListIds.set([]);
    this.playlistService.activeListName.set(null);
    this.playlistService.activePlaylistId.set(null);
    this.limit.set(30);
  }

  playPlaylist() {
    const ids = this.playlistService.activeListIds();
    if (ids.length > 0) {
      this.playlistService.autoPlayPlaylist.set(true);
      this.router.navigate(['/player'], { queryParams: { id: ids[0] } });
    }
  }

  shareActivePlaylist() {
    const ids = this.playlistService.activeListIds();
    const name = this.playlistService.activeListName() || 'Playlist';
    
    const id = this.playlistService.activePlaylistId();
    const pl = this.playlistService.playlists().find(p => p.id === id);
    const songSettings = pl ? pl.songSettings : undefined;

    this.playlistService.sharePlaylistQR(ids, name, songSettings);
  }

  async importPlaylist() {
    const modal = await this.modalCtrl.create({
      component: QrScannerComponent
    });
    await modal.present();

    const { data } = await modal.onWillDismiss();
    if (!data) return;
    this.handleScannedData(data);
  }

  async deleteActivePlaylist() {
    const id = this.playlistService.activePlaylistId();
    const name = this.playlistService.activeListName();
    if (!id || !name) return;

    const isRemote = this.isRemotePlaylist();

    const alert = await this.alertCtrl.create({
      header: isRemote ? 'Rimuovi Playlist' : 'Elimina Playlist',
      message: isRemote ? `Vuoi davvero rimuovere la playlist "${name}"?` : `Vuoi davvero eliminare "${name}"?`,
      buttons: [
        { text: 'Annulla', role: 'cancel' },
        { 
          text: isRemote ? 'Rimuovi' : 'Elimina', 
          role: 'destructive',
          handler: () => {
            if (isRemote) {
              this.playlistService.clearRemotePlaylist();
            } else {
              this.playlistService.deletePlaylist(id);
            }
            this.clearSpecialList();
          }
        }
      ]
    });
    await alert.present();
  }

  editPlaylist() {
    const ids = this.playlistService.activeListIds();
    const name = this.playlistService.activeListName();
    
    // Prova a recuperare l'ID se stiamo editando una playlist salvata
    const found = this.playlistService.playlists().find(p => p.name === name);
    if (found) {
      this.playlistService.activePlaylistId.set(found.id);
    }

    this.playlistService.selectedIds.set(new Set(ids));
    const songs = ids.map(id => this.findCanto(id)).filter((c): c is any => !!c);
    this.reorderList.set(songs);
    this.playlistService.selectionMode.set(true);
    this.isAddingSongs.set(false); // Default to reorder view
    
    // Svuota la playlist attiva per mostrare tutto l'elenco in modalità selezione
    this.playlistService.activeListIds.set([]);
    this.playlistService.activeListName.set(name);
  }

  toggleSongSelection(id: string) {
    if (!this.playlistService.selectionMode()) {
      const activeIds = this.playlistService.activeListIds();
      const activeName = this.playlistService.activeListName();
      
      if (activeIds.length > 0) {
        // Se selezioniamo i numerini di una playlist attiva, non andiamo in modifica di quella playlist
        // ma avviamo la selezione partendo da questa lista per creare una nuova playlist.
        this.playlistService.activePlaylistId.set(null);
        
        const clickedCanto = this.findCanto(id);
        if (clickedCanto) {
          this.playlistService.selectedIds.set(new Set([clickedCanto.id]));
          this.reorderList.set([clickedCanto]);
        }
        
        this.playlistService.selectionMode.set(true);
        this.isAddingSongs.set(true); // Rimaniamo sulla lista filtrata per selezionare altri canti
        return;
      }
    }

    this.playlistService.toggleSongSelection(id);
  }

  drop(event: CdkDragDrop<any[]>) {
    const arr = [...this.reorderList()];
    moveItemInArray(arr, event.previousIndex, event.currentIndex);
    this.reorderList.set(arr);
  }

  toggleAddingSongs() {
    this.isAddingSongs.update(v => !v);
    this.limit.set(10);
  }

  getCommunitySongNumber(canto: any): string | null {
    if (!this.comunitaService.comunitaCode() || !this.comunitaService.isFilterActive()) return null;
    const cantiInfo = this.comunitaService.comunitaCantiInfo();
    const info = cantiInfo.find(x => x.id_canti === canto.id_canti || x.id_canti === Number(canto.id));
    return info && info.num_canto ? info.num_canto.toString() : null;
  }

  getMySongNumber(canto: any): number {
    if (!canto || !canto.id) return 0;
    const index = this.myCantiService.myCanti().findIndex(c => c.id === canto.id);
    return index !== -1 ? index + 1 : 0;
  }

  toggleComunitaFilter() {
    if (this.comunitaService.comunitaCode()) {
      this.comunitaService.isFilterActive.update(v => !v);
    }
    this.activeFilterType.set(null);
  }

  private massCardStartX: number = 0;
  private massCardStartY: number = 0;

  onMassCardTouchStart(event: TouchEvent) {
    if (event.touches.length === 1) {
      this.massCardStartX = event.touches[0].clientX;
      this.massCardStartY = event.touches[0].clientY;
    }
  }

  onMassCardTouchEnd(event: TouchEvent) {
    if (event.changedTouches.length === 1) {
      const endX = event.changedTouches[0].clientX;
      const endY = event.changedTouches[0].clientY;
      const diffX = endX - this.massCardStartX;
      const diffY = endY - this.massCardStartY;

      // Ensure it is a horizontal swipe (diffX is much larger than diffY)
      if (Math.abs(diffX) > 60 && Math.abs(diffY) < 40) {
        // Prevent triggering click expansion
        event.stopPropagation();
        event.preventDefault();

        if (diffX > 0) {
          // Swiped right -> go to PREVIOUS date
          this.navigateMassDate(-1);
        } else {
          // Swiped left -> go to NEXT date
          this.navigateMassDate(1);
        }
      }
    }
  }

  async navigateMassDate(direction: number) {
    const list = this.cantiLettureService.availableMasses();
    if (list.length === 0) return;
    
    const currentDate = this.cantiLettureService.selectedMassDate();
    if (!currentDate) {
      this.cantiLettureService.selectedMassDate.set(list[0].date);
      return;
    }

    const currentIndex = list.findIndex(m => m.date === currentDate);
    if (currentIndex === -1) {
      this.cantiLettureService.selectedMassDate.set(list[0].date);
      return;
    }

    const nextIndex = currentIndex + direction;
    if (nextIndex >= 0 && nextIndex < list.length) {
      // Set the next/prev date
      this.cantiLettureService.selectedMassDate.set(list[nextIndex].date);
      
      const toast = await this.toastCtrl.create({
        message: `Messa: ${list[nextIndex].day} ${this.formatCompactDate(list[nextIndex].date)}`,
        duration: 1500,
        color: 'secondary',
        position: 'bottom'
      });
      await toast.present();
    } else {
      // "quando le messe sono finite rimani sull'ultima valorizzata, non dare errore"
      const targetIndex = direction > 0 ? list.length - 1 : 0;
      this.cantiLettureService.selectedMassDate.set(list[targetIndex].date);
      
      const toast = await this.toastCtrl.create({
        message: direction > 0 ? 'Nessun\'altra messa futura disponibile.' : 'Nessun\'altra messa passata disponibile.',
        duration: 1500,
        color: 'medium',
        position: 'bottom'
      });
      await toast.present();
    }
  }

  private formatCompactDate(dateStr: string): string {
    const parts = dateStr.split('-');
    if (parts.length === 3) {
      return `${parts[2]}/${parts[1]}`;
    }
    return dateStr;
  }
}

