import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, BehaviorSubject } from 'rxjs';
import { map, tap, catchError, shareReplay } from 'rxjs/operators';
import { environment } from '../../../environments/environment';
import { Menu, Metadata, Badge, CTA, DashboardBadge, BadgeHealthCheck } from '../models';

/**
 * Service de communication avec l'API CHAPS
 * Gère les métadonnées, menus, et configuration UI
 */
@Injectable({
  providedIn: 'root'
})
export class ChapsService {
  private readonly baseUrl = environment.API_URL;
  private readonly apiKey = environment.X_APY_KEY;

  // Cache des métadonnées par module
  private metadataCache = new Map<string, any>();
  private menuCache: Menu[] | null = null;

  // Subjects pour les données partagées
  private menusSubject = new BehaviorSubject<Menu[]>([]);
  public menus$ = this.menusSubject.asObservable();

  // Cache et observables pour les badges
  private dashboardBadges$ = new BehaviorSubject<Badge[]>([]);
  public badges$ = this.dashboardBadges$.asObservable();
  private lastHealthCheck: BadgeHealthCheck | null = null;

  constructor(private http: HttpClient) {}

  /**
   * Récupère la structure des menus depuis CHAPS
   */
  getMenus(): Observable<Menu[]> {
    if (this.menuCache) {
      return new Observable(observer => {
        observer.next(this.menuCache!);
        observer.complete();
      });
    }

    return this.http.get<Menu[]>(`${this.baseUrl}v1/menus`).pipe(
      tap(menus => {
        this.menuCache = menus;
        this.menusSubject.next(menus);
      }),
      catchError(this.handleError('getMenus'))
    );
  }

  /**
   * Récupère les métadonnées d'un module spécifique
   */
  getMetadata(moduleName: string): Observable<Metadata> {
    // Vérifier le cache d'abord
    if (this.metadataCache.has(moduleName)) {
      return new Observable(observer => {
        observer.next(this.metadataCache.get(moduleName));
        observer.complete();
      });
    }

    return this.http.post<any>(`${this.baseUrl}v1/metadata/${moduleName}`, {}).pipe(
      map(response => this.transformMetadata(response)),
      tap(metadata => this.metadataCache.set(moduleName, metadata)),
      catchError(this.handleError('getMetadata'))
    );
  }

  /**
   * Récupère les badges/KPIs d'un module
   */
  getBadges(moduleName: string): Observable<Badge[]> {
    return this.getMetadata(moduleName).pipe(
      map(metadata => metadata.ListView?.badges || [])
    );
  }

  /**
   * Récupère les CTAs (boutons d'action) d'un module
   */
  getCTAs(moduleName: string): Observable<CTA[]> {
    return this.getMetadata(moduleName).pipe(
      map(metadata => metadata.ListView?.cta || [])
    );
  }

  /**
   * Vide le cache des métadonnées
   */
  clearCache(): void {
    this.metadataCache.clear();
    this.menuCache = null;
  }

  /**
   * Vide le cache d'un module spécifique
   */
  clearModuleCache(moduleName: string): void {
    this.metadataCache.delete(moduleName);
  }

  /**
   * Transforme la réponse API en structure typée
   */
  private transformMetadata(response: any): Metadata {
    return {
      CreateView: {
        fields: response.CreateView?.fields || []
      },
      ListView: {
        list: response.ListView?.list || [],
        cta: response.ListView?.cta || [],
        badges: response.ListView?.badges || []
      },
      DetailView: {
        fields: response.DetailView?.fields || [],
        headers: response.DetailView?.headers || []
      },
      UpdateView: {
        fields: response.UpdateView?.fields || []
      }
    };
  }

  /**
   * Gestionnaire d'erreur générique
   */
  private handleError(operation = 'operation') {
    return (error: any): Observable<any> => {
      console.error(`${operation} failed:`, error);
      
      // Retourner une valeur par défaut selon l'opération
      switch (operation) {
        case 'getMenus':
          return new Observable(observer => {
            observer.next([]);
            observer.complete();
          });
        case 'getMetadata':
          return new Observable(observer => {
            observer.next(this.getEmptyMetadata());
            observer.complete();
          });
        default:
          throw error;
      }
    };
  }

  /**
   * Retourne une structure de métadonnées vide
   */
  private getEmptyMetadata(): Metadata {
    return {
      CreateView: { fields: [] },
      ListView: { list: [], cta: [], badges: [] },
      DetailView: { fields: [], headers: [] },
      UpdateView: { fields: [] }
    };
  }

  // ==================== NOUVELLES MÉTHODES BADGES ====================

  /**
   * Récupère tous les badges depuis l'API CHAPS
   */
  getAllBadges(): Observable<Badge[]> {
    return this.http.get<{ success: boolean; data: Badge[] }>(`${this.baseUrl}v1/badges`).pipe(
      map(response => response.data || []),
      catchError(this.handleError('getAllBadges'))
    );
  }

  /**
   * Récupère les badges du dashboard avec données ESTAIR
   * Cette méthode utilise la communication API sécurisée CHAPS ↔ ESTAIR
   */
  getDashboardBadges(): Observable<DashboardBadge> {
    return this.http.get<DashboardBadge>(`${this.baseUrl}v1/badges/dashboard`).pipe(
      tap(response => {
        if (response.success && response.data) {
          this.dashboardBadges$.next(response.data);
        }
      }),
      shareReplay(1),
      catchError(this.handleError('getDashboardBadges'))
    );
  }

  /**
   * Récupère les badges commerciaux
   */
  getCommercialBadges(): Observable<Badge[]> {
    return this.http.get<{ success: boolean; data: Badge[] }>(`${this.baseUrl}v1/badges/commercial`).pipe(
      map(response => response.data || []),
      catchError(this.handleError('getCommercialBadges'))
    );
  }

  /**
   * Récupère un badge spécifique par ID
   */
  getBadgeById(id: number): Observable<Badge> {
    return this.http.get<{ success: boolean; data: Badge }>(`${this.baseUrl}v1/badges/${id}`).pipe(
      map(response => response.data),
      catchError(this.handleError('getBadgeById'))
    );
  }

  /**
   * Effectue un test de santé de l'architecture CHAPS ↔ ESTAIR
   * Vérifie l'isolation complète et la communication API
   */
  getHealthCheck(): Observable<BadgeHealthCheck> {
    return this.http.get<BadgeHealthCheck>(`${this.baseUrl}v1/badges/health`).pipe(
      tap(health => {
        this.lastHealthCheck = health;
        console.log('🏥 Health Check CHAPS ↔ ESTAIR:', health);
      }),
      catchError(this.handleError('getHealthCheck'))
    );
  }

  /**
   * Rafraîchit les badges du dashboard
   * Force la récupération des nouvelles données depuis ESTAIR
   */
  refreshDashboard(): Observable<DashboardBadge> {
    // Vider le cache et récupérer de nouvelles données
    return this.getDashboardBadges();
  }

  /**
   * Récupère le dernier health check en cache
   */
  getLastHealthCheck(): BadgeHealthCheck | null {
    return this.lastHealthCheck;
  }

  /**
   * Vérifie si l'architecture est saine
   */
  isArchitectureHealthy(): boolean {
    return this.lastHealthCheck?.status === 'healthy';
  }

  /**
   * Obtient les métriques de performance de la communication API
   */
  getApiLatency(): number {
    return this.lastHealthCheck?.tests?.api_communication?.latency_ms || 0;
  }
}

