import { Injectable, signal, inject, effect } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Storage } from '@ionic/storage-angular';
import { firstValueFrom } from 'rxjs';

export interface Suggestion {
  id_canto?: number;
  id_canti?: number;
  peso?: number;
  score?: number;
}

export interface MassDetails {
  title: string;
  day: string;
  summary?: string;
  suggestions: { [moment: string]: Suggestion[] } | Suggestion[];
}

export interface CantiLettureData {
  generated_at: string;
  week_start: string;
  week_end: string;
  masses: { [date: string]: MassDetails };
}

export interface AvailableMass {
  date: string;
  title: string;
  day: string;
  formattedLabel: string;
}

@Injectable({
  providedIn: 'root'
})
export class CantiLettureService {
  private http = inject(HttpClient);
  private storage = inject(Storage);

  private _storage: Storage | null = null;
  public data = signal<CantiLettureData | null>(null);
  public selectedMassDate = signal<string | null>(null);
  public availableMasses = signal<AvailableMass[]>([]);
  public suggestionsMap = signal<Map<number, number>>(new Map()); // id_canto -> peso
  public suggestionsMomentsMap = signal<Map<number, string[]>>(new Map()); // id_canto -> moments[]

  private JSON_URL = 'https://api.canticristiani.it/cantiletture.json';
  private SECURE_JSON_URL = '/api/cantiletture.json';

  constructor() {
    this.init();

    // Effect to auto-update suggestions maps when selectedMassDate or data changes
    effect(() => {
      const activeDate = this.selectedMassDate();
      const currentData = this.data();
      const newMap = new Map<number, number>();
      const newMomentsMap = new Map<number, string[]>();

      if (activeDate && currentData && currentData.masses[activeDate]) {
        const mass = currentData.masses[activeDate];
        if (mass.suggestions) {
          if (Array.isArray(mass.suggestions)) {
            // Legacy flat suggestions format
            mass.suggestions.forEach(s => {
              if (s) {
                const id = s.id_canto || (s as any).id_canti;
                const weight = s.peso !== undefined ? s.peso : (s as any).score;
                if (id) {
                  newMap.set(id, weight);
                  newMomentsMap.set(id, ['Generale']);
                }
              }
            });
          } else {
            // New moment-grouped suggestions format
            Object.keys(mass.suggestions).forEach(moment => {
              const momentSuggestions = (mass.suggestions as any)[moment];
              if (Array.isArray(momentSuggestions)) {
                momentSuggestions.forEach(s => {
                  if (s) {
                    const id = s.id_canto || (s as any).id_canti;
                    const weight = s.peso !== undefined ? s.peso : (s as any).score;
                    if (id) {
                      // Save max weight
                      const existingWeight = newMap.get(id) || 0;
                      if (weight > existingWeight) {
                        newMap.set(id, weight);
                      }

                      // Save liturgical moment
                      const existingMoments = newMomentsMap.get(id) || [];
                      if (!existingMoments.includes(moment)) {
                        newMomentsMap.set(id, [...existingMoments, moment]);
                      }
                    }
                  }
                });
              }
            });
          }
        }
      }
      this.suggestionsMap.set(newMap);
      this.suggestionsMomentsMap.set(newMomentsMap);
    });

    // Effect to persist selectedMassDate to local storage
    effect(() => {
      const activeDate = this.selectedMassDate();
      if (activeDate) {
        localStorage.setItem('selected-mass-date', activeDate);
      }
    });
  }

  async init() {
    // We assume CantiService has already created the storage, but to be safe:
    this._storage = await this.storage.create();
    
    // Load cached values
    const cachedData = await this._storage?.get('cantiletture_data');
    if (cachedData) {
      this.processData(cachedData);
    }

    const savedDate = localStorage.getItem('selected-mass-date');
    if (savedDate) {
      this.selectedMassDate.set(savedDate);
    }

    // Fetch fresh data
    await this.fetchData();
  }

  async fetchData() {
    try {
      let fetchedData: CantiLettureData | null = null;
      
      const isProduction = window.location.hostname.includes('canticristiani.it');
      const primaryUrl = isProduction 
        ? `${window.location.origin}${this.SECURE_JSON_URL}` 
        : 'https://www.canticristiani.it/api/cantiletture.json';
      const fallbackUrl = isProduction 
        ? 'https://www.canticristiani.it/api/cantiletture.json' 
        : this.JSON_URL;

      try {
        console.log('Fetching mass data from primary URL:', primaryUrl);
        fetchedData = await firstValueFrom(this.http.get<CantiLettureData>(`${primaryUrl}?t=${Date.now()}`));
      } catch (err) {
        console.warn('Primary fetch failed, trying fallback URL...', fallbackUrl, err);
        try {
          fetchedData = await firstValueFrom(this.http.get<CantiLettureData>(`${fallbackUrl}?t=${Date.now()}`));
        } catch (fallbackErr) {
          console.error('Fallback fetch also failed:', fallbackErr);
        }
      }

      if (fetchedData && fetchedData.masses) {
        this.processData(fetchedData);
        await this._storage?.set('cantiletture_data', fetchedData);
      }
    } catch (err) {
      console.error('Failed to fetch cantiletture.json from both primary and fallback URLs', err);
    }
  }

  private processData(json: CantiLettureData) {
    this.data.set(json);

    // Build available masses array
    const massesList: AvailableMass[] = [];
    const keys = Object.keys(json.masses).sort(); // Sort chronological

    keys.forEach(key => {
      const mass = json.masses[key];
      const parts = key.split('-');
      let formattedLabel = key;
      if (parts.length === 3) {
        formattedLabel = `${parts[2]}/${parts[1]}`;
      }
      const day = mass.day || '';
      const title = mass.title || '';
      
      massesList.push({
        date: key,
        title: title,
        day: day,
        formattedLabel: `${day} ${formattedLabel}`
      });
    });

    this.availableMasses.set(massesList);

    // Always select today's mass if available on load, else find closest future date
    if (massesList.length > 0) {
      const now = new Date();
      const year = now.getFullYear();
      const month = String(now.getMonth() + 1).padStart(2, '0');
      const day = String(now.getDate()).padStart(2, '0');
      const todayStr = `${year}-${month}-${day}`;
      const match = massesList.find(m => m.date === todayStr);
      if (match) {
        this.selectedMassDate.set(match.date);
      } else {
        // If today is not present, find the first date that is in the future
        const futureMatch = massesList.find(m => m.date >= todayStr);
        if (futureMatch) {
          this.selectedMassDate.set(futureMatch.date);
        } else {
          // Otherwise fall back to the last available mass date (closest to today)
          this.selectedMassDate.set(massesList[massesList.length - 1].date);
        }
      }
    }
  }

  setSelectedMass(date: string) {
    this.selectedMassDate.set(date);
  }
}
