import { Injectable, signal, inject, effect } from '@angular/core';
import { HttpClient, HttpRequest, HttpEventType, HttpResponse } from '@angular/common/http';
import { SettingsService } from './settings.service';
import { Canto } from './canti.service';

export interface ParrocchiaItem {
  id_parrocchia: number;
  nome: string;
  codice: string;
  mail: string;
  guid_parrocchia: string;
}

export interface ParrocchiaCantiItem {
  id_parrocchia: number;
  id_canti: number;
  num_canto: number;
}

export interface CantiSettingsItem {
  id_canti: number;
  speed: number;
  tonalita: number;
}

export interface ComunitaScaletta {
  id: string;
  name: string;
  date: string;
  ids: string[];
}

export interface GetAllAppTablesResponse {
  parrocchia?: { data: ParrocchiaItem[] };
  parrocchia_canti?: { data: ParrocchiaCantiItem[] };
  canti_settings?: { data: CantiSettingsItem[] };
}

@Injectable({
  providedIn: 'root'
})
export class ComunitaService {
  private http = inject(HttpClient);
  private settingsService = inject(SettingsService);

  public comunitaCode = signal<string>('');
  public comunitaNome = signal<string>('');
  public comunitaMail = signal<string>('');
  public comunitaCantiIds = signal<(number | string)[]>([]);
  public comunitaCantiInfo = signal<ParrocchiaCantiItem[]>([]);
  public comunitaCantiSettings = signal<CantiSettingsItem[]>([]);
  public comunitaCantiPersonali = signal<Canto[]>([]);
  public comunitaScalette = signal<ComunitaScaletta[]>([]);
  public isFilterActive = signal<boolean>(false);
  public loading = signal<boolean>(false);
  public loadingProgress = signal<number>(0);

  constructor() {
    const savedCode = localStorage.getItem('comunita-code');
    const savedNome = localStorage.getItem('comunita-nome');
    const savedMail = localStorage.getItem('comunita-mail');
    const savedCanti = localStorage.getItem('comunita-canti-ids');
    const savedInfo = localStorage.getItem('comunita-canti-info');
    const savedSettings = localStorage.getItem('comunita-canti-settings');
    const savedCantiPersonali = localStorage.getItem('comunita-canti-personali');
    const savedScalette = localStorage.getItem('comunita-scalette');
    const savedFilterActive = localStorage.getItem('comunita-filter-active') === 'true';

    if (savedCode) {
      this.comunitaCode.set(savedCode);
      // Run background refresh 1 second after startup to fetch any new custom canti or updates
      // but only if the community feature is enabled in settings
      setTimeout(() => {
        if (!this.settingsService.comunitaEnabled()) {
          // Community is disabled: skip refresh to avoid re-enabling the filter
          return;
        }
        this.setComunitaCode(savedCode).catch(err => {
          console.warn('Failed background community refresh at startup:', err);
        });
      }, 1000);
    }
    if (savedNome) this.comunitaNome.set(savedNome);
    if (savedMail) this.comunitaMail.set(savedMail);
    if (savedCanti) {
      try { this.comunitaCantiIds.set(JSON.parse(savedCanti)); } catch (e) {}
    }
    if (savedInfo) {
      try { this.comunitaCantiInfo.set(JSON.parse(savedInfo)); } catch (e) {}
    }
    if (savedSettings) {
      try { this.comunitaCantiSettings.set(JSON.parse(savedSettings)); } catch (e) {}
    }
    if (savedCantiPersonali) {
      try { this.comunitaCantiPersonali.set(JSON.parse(savedCantiPersonali)); } catch (e) {}
    }
    if (savedScalette) {
      try { this.comunitaScalette.set(JSON.parse(savedScalette)); } catch (e) {}
    }
    this.isFilterActive.set(savedFilterActive);

    effect(() => {
      localStorage.setItem('comunita-code', this.comunitaCode());
      localStorage.setItem('comunita-nome', this.comunitaNome());
      localStorage.setItem('comunita-mail', this.comunitaMail());
      localStorage.setItem('comunita-canti-ids', JSON.stringify(this.comunitaCantiIds()));
      localStorage.setItem('comunita-canti-info', JSON.stringify(this.comunitaCantiInfo()));
      localStorage.setItem('comunita-canti-settings', JSON.stringify(this.comunitaCantiSettings()));
      localStorage.setItem('comunita-canti-personali', JSON.stringify(this.comunitaCantiPersonali()));
      localStorage.setItem('comunita-scalette', JSON.stringify(this.comunitaScalette()));
      localStorage.setItem('comunita-filter-active', this.isFilterActive().toString());
    });

    effect(() => {
      if (!this.settingsService.comunitaEnabled()) {
        this.isFilterActive.set(false);
      }
    });
  }

  private fetchWithProgress<T>(url: string): Promise<T> {
    return new Promise<T>((resolve, reject) => {
      const req = new HttpRequest('GET', url, {
        reportProgress: true,
        responseType: 'json'
      });

      this.http.request<T>(req).subscribe({
        next: (event) => {
          if (event.type === HttpEventType.DownloadProgress) {
            if (event.total && event.total > 0) {
              const pct = Math.round((event.loaded / event.total) * 100);
              this.loadingProgress.set(pct);
            } else {
              // No Content-Length header — simulate gradual progress up to 85%
              const simulated = Math.min(85, this.loadingProgress() + 12);
              this.loadingProgress.set(simulated);
            }
          } else if (event instanceof HttpResponse) {
            this.loadingProgress.set(100);
            resolve(event.body as T);
          }
        },
        error: (err) => reject(err)
      });
    });
  }

  async setComunitaCode(code: string): Promise<boolean> {
    const trimmedCode = code.trim();
    if (!trimmedCode) {
      this.comunitaCode.set('');
      this.comunitaNome.set('');
      this.comunitaMail.set('');
      this.comunitaCantiIds.set([]);
      this.comunitaCantiInfo.set([]);
      this.comunitaCantiSettings.set([]);
      this.comunitaCantiPersonali.set([]);
      this.comunitaScalette.set([]);
      this.isFilterActive.set(false);
      return true;
    }

    this.loading.set(true);
    this.loadingProgress.set(0);

    // 1. Try to fetch from the actual production API
    try {
      const url = `https://libretto.mmcinet.eu/canti/api/v3/get_all_app_tables?uuid=pwa-cc-uuid&email=&platform=browser&version=1.0&gruppo=${trimmedCode}&all_song=false&t=${Date.now()}`;
      const data = await this.fetchWithProgress<GetAllAppTablesResponse>(url);

      if (data && data.parrocchia?.data && data.parrocchia.data.length > 0) {
        const parrocchia = data.parrocchia.data[0];
        const cantiList = data.parrocchia_canti?.data || [];
        const settingsList = data.canti_settings?.data || [];

        // Parse canti_personali (custom unvalidated community canti)
        const cantiPersonaliList = (data as any).canti_personali?.data || [];
        const mappedCantiPersonali = cantiPersonaliList.map((cp: any) => ({
          id: cp.id_canti.toString(),
          id_canti: cp.id_canti,
          titolo: cp.titolo,
          testo: cp.accordi || '',
          accordi: cp.accordi || '',
          autore: cp.autore || '',
          link_youtube: cp.link_youtube || '',
          id_momenti: [],
          data_update: cp.data_update || '',
          nonValidato: Number(cp.stato) === 10,
          isPersonal: true
        }));

        this.comunitaCode.set(trimmedCode);
        this.comunitaNome.set(parrocchia.nome || `Comunità ${trimmedCode}`);
        this.comunitaMail.set(parrocchia.mail || '');
        this.comunitaCantiInfo.set(cantiList);
        this.comunitaCantiIds.set(cantiList.map(c => c.id_canti));
        this.comunitaCantiSettings.set(settingsList);
        this.comunitaCantiPersonali.set(mappedCantiPersonali);

        // Parse scalette (setlists) from lista_nome + lista_esecuzione
        const listaNomelList = (data as any).lista_nome?.data || [];
        const listaEsecuzioneList = (data as any).lista_esecuzione?.data || [];

        // Group lista_esecuzione by id_lista and keep order by progr
        const esecuzioniByLista = new Map<string, { id_canti: string; progr: number }[]>();
        for (const item of listaEsecuzioneList) {
          if (!esecuzioniByLista.has(item.id_lista)) {
            esecuzioniByLista.set(item.id_lista, []);
          }
          esecuzioniByLista.get(item.id_lista)!.push({
            id_canti: String(item.id_canti),
            progr: Number(item.progr) || 0
          });
        }

        // Build scalette array sorted by date (most recent first)
        const scalette: ComunitaScaletta[] = listaNomelList
          .map((ln: any) => {
            const songs = esecuzioniByLista.get(ln.id_lista) || [];
            songs.sort((a: any, b: any) => a.progr - b.progr);
            return {
              id: `comunita_${ln.id_lista}`,
              name: ln.nome || 'Scaletta',
              date: ln.progr || '',
              ids: songs.map((s: any) => s.id_canti)
            };
          })
          .filter((s: ComunitaScaletta) => s.ids.length > 0)
          .sort((a: ComunitaScaletta, b: ComunitaScaletta) => b.date.localeCompare(a.date));

        this.comunitaScalette.set(scalette);
        this.isFilterActive.set(true);
        this.loading.set(false);
        return true;
      }
    } catch (err) {
      console.warn('Failed to fetch from production API, trying fallback...', err);
      this.loadingProgress.set(0);
    }

    // 2. Fallback to static community JSON
    try {
      const isProduction = window.location.hostname.includes('canticristiani.it');
      const origin = isProduction ? window.location.origin : 'https://www.canticristiani.it';
      const fallbackUrl = `${origin}/api/comunita_${trimmedCode}.json?t=${Date.now()}`;

      interface StaticComunitaData {
        id_comunita: string;
        nome_comunita: string;
        canti: (number | string)[];
      }

      const staticData = await this.fetchWithProgress<StaticComunitaData>(fallbackUrl);
      if (staticData && staticData.canti) {
        this.comunitaCode.set(trimmedCode);
        this.comunitaNome.set(staticData.nome_comunita || `Comunità ${trimmedCode}`);
        this.comunitaCantiIds.set(staticData.canti);

        const mockInfo = staticData.canti.map((id, index) => ({
          id_parrocchia: 1,
          id_canti: Number(id),
          num_canto: index + 1
        }));

        this.comunitaCantiInfo.set(mockInfo);
        this.comunitaCantiSettings.set([]);
        this.comunitaCantiPersonali.set([]);
        this.comunitaScalette.set([]);
        this.isFilterActive.set(true);
        this.loading.set(false);
        return true;
      }
    } catch (err) {
      console.error('All community fetch strategies failed:', err);
    }

    this.loading.set(false);
    return false;
  }
}
