/**
 * ⚙️ ConfigurationService - Gestion centralisée de la configuration
 * Remplace les configurations éparpillées du GlobalService
 */

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { environment } from '../../../environments/environment';

export interface AppConfiguration {
  api: {
    baseUrl: string;
    dataUrl: string;
    apiKey: string;
    dataApiKey: string;
    timeout: number;
    retryAttempts: number;
  };
  cache: {
    defaultTtl: number;
    maxSize: number;
    cleanupInterval: number;
    enableMetrics: boolean;
  };
  auth: {
    refreshThreshold: number;
    tokenStorageKey: string;
    userStorageKey: string;
  };
  ui: {
    theme: 'light' | 'dark' | 'auto';
    language: string;
    dateFormat: string;
    timeFormat: string;
    pageSize: number;
    maxPageSize: number;
  };
  features: {
    enableDebugMode: boolean;
    enableAnalytics: boolean;
    enableNotifications: boolean;
    enableOfflineMode: boolean;
  };
  logging: {
    level: 'error' | 'warn' | 'info' | 'debug';
    enableConsole: boolean;
    enableRemote: boolean;
  };
}

@Injectable({
  providedIn: 'root'
})
export class ConfigurationService {
  private readonly CONFIG_STORAGE_KEY = 'app_config';
  private readonly defaultConfiguration: AppConfiguration;
  private configuration = new BehaviorSubject<AppConfiguration>(this.createDefaultConfig());

  constructor() {
    this.defaultConfiguration = this.createDefaultConfig();
    this.loadConfiguration();
  }

  /**
   * Configuration observable
   */
  get config$(): Observable<AppConfiguration> {
    return this.configuration.asObservable();
  }

  /**
   * Configuration actuelle
   */
  get currentConfig(): AppConfiguration {
    return this.configuration.value;
  }

  /**
   * Obtenir une section spécifique de la configuration
   */
  getApiConfig() {
    return this.currentConfig.api;
  }

  getCacheConfig() {
    return this.currentConfig.cache;
  }

  getAuthConfig() {
    return this.currentConfig.auth;
  }

  getUIConfig() {
    return this.currentConfig.ui;
  }

  getFeaturesConfig() {
    return this.currentConfig.features;
  }

  getLoggingConfig() {
    return this.currentConfig.logging;
  }

  /**
   * Mettre à jour la configuration complète
   */
  updateConfiguration(newConfig: Partial<AppConfiguration>): void {
    const updatedConfig = this.mergeConfigurations(this.currentConfig, newConfig);
    this.configuration.next(updatedConfig);
    this.saveConfiguration(updatedConfig);
    
    console.log('Configuration mise à jour:', updatedConfig);
  }

  /**
   * Mettre à jour une section spécifique
   */
  updateApiConfig(apiConfig: Partial<AppConfiguration['api']>): void {
    this.updateConfiguration({ api: { ...this.currentConfig.api, ...apiConfig } });
  }

  updateCacheConfig(cacheConfig: Partial<AppConfiguration['cache']>): void {
    this.updateConfiguration({ cache: { ...this.currentConfig.cache, ...cacheConfig } });
  }

  updateAuthConfig(authConfig: Partial<AppConfiguration['auth']>): void {
    this.updateConfiguration({ auth: { ...this.currentConfig.auth, ...authConfig } });
  }

  updateUIConfig(uiConfig: Partial<AppConfiguration['ui']>): void {
    this.updateConfiguration({ ui: { ...this.currentConfig.ui, ...uiConfig } });
  }

  updateFeaturesConfig(featuresConfig: Partial<AppConfiguration['features']>): void {
    this.updateConfiguration({ features: { ...this.currentConfig.features, ...featuresConfig } });
  }

  updateLoggingConfig(loggingConfig: Partial<AppConfiguration['logging']>): void {
    this.updateConfiguration({ logging: { ...this.currentConfig.logging, ...loggingConfig } });
  }

  /**
   * Réinitialiser à la configuration par défaut
   */
  resetToDefault(): void {
    const defaultConfig = this.createDefaultConfig();
    this.configuration.next(defaultConfig);
    this.saveConfiguration(defaultConfig);
    
    console.log('Configuration réinitialisée aux valeurs par défaut');
  }

  /**
   * Sauvegarder la configuration en localStorage
   */
  saveConfiguration(config?: AppConfiguration): void {
    const configToSave = config || this.currentConfig;
    try {
      localStorage.setItem(this.CONFIG_STORAGE_KEY, JSON.stringify(configToSave));
    } catch (error) {
      console.error('Erreur lors de la sauvegarde de la configuration:', error);
    }
  }

  /**
   * Charger la configuration depuis localStorage
   */
  loadConfiguration(): void {
    try {
      const savedConfig = localStorage.getItem(this.CONFIG_STORAGE_KEY);
      if (savedConfig) {
        const parsedConfig = JSON.parse(savedConfig);
        const mergedConfig = this.mergeConfigurations(this.defaultConfiguration, parsedConfig);
        this.configuration.next(mergedConfig);
        console.log('Configuration chargée depuis localStorage');
      }
    } catch (error) {
      console.error('Erreur lors du chargement de la configuration:', error);
      this.configuration.next(this.defaultConfiguration);
    }
  }

  /**
   * Obtenir une valeur de configuration par chemin
   */
  getValue<T>(path: string): T | undefined {
    return this.getValueByPath(this.currentConfig, path) as T;
  }

  /**
   * Définir une valeur de configuration par chemin
   */
  setValue(path: string, value: any): void {
    const updatedConfig = { ...this.currentConfig };
    this.setValueByPath(updatedConfig, path, value);
    this.updateConfiguration(updatedConfig);
  }

  /**
   * Vérifier si une fonctionnalité est activée
   */
  isFeatureEnabled(featureName: keyof AppConfiguration['features']): boolean {
    return this.currentConfig.features[featureName];
  }

  /**
   * Obtenir les paramètres d'environnement
   */
  getEnvironmentInfo() {
    return {
      production: environment.production,
      version: '1.0.0',
      api: {
        baseUrl: environment.API_URL,
        dataUrl: environment.DATA_URL,
        hasApiKey: !!environment.X_APY_KEY,
        hasDataApiKey: !!environment.DATA_APY_KEY
      },
      build: {
        timestamp: new Date().toISOString(),
        environment: 'development'
      }
    };
  }

  /**
   * Créer la configuration par défaut
   */
  private createDefaultConfig(): AppConfiguration {
    return {
      api: {
        baseUrl: environment.API_URL || 'http://localhost:3000/api/',
        dataUrl: environment.DATA_URL || 'http://localhost:3000/data/',
        apiKey: environment.X_APY_KEY || '',
        dataApiKey: environment.DATA_APY_KEY || '',
        timeout: 30000,
        retryAttempts: 2
      },
      cache: {
        defaultTtl: 30000, // 30 secondes
        maxSize: 100,
        cleanupInterval: 60000, // 1 minute
        enableMetrics: true
      },
      auth: {
        refreshThreshold: 5 * 60 * 1000, // 5 minutes
        tokenStorageKey: 'auth_token',
        userStorageKey: 'auth_user'
      },
      ui: {
        theme: 'light',
        language: 'fr',
        dateFormat: 'DD/MM/YYYY',
        timeFormat: 'HH:mm:ss',
        pageSize: 20,
        maxPageSize: 100
      },
      features: {
        enableDebugMode: !environment.production,
        enableAnalytics: environment.production,
        enableNotifications: true,
        enableOfflineMode: false
      },
      logging: {
        level: environment.production ? 'warn' : 'debug',
        enableConsole: true,
        enableRemote: environment.production
      }
    };
  }

  /**
   * Fusionner deux configurations
   */
  private mergeConfigurations(
    defaultConfig: AppConfiguration, 
    userConfig: Partial<AppConfiguration>
  ): AppConfiguration {
    const merged = { ...defaultConfig };
    
    Object.keys(userConfig).forEach(key => {
      const userValue = (userConfig as any)[key];
      if (userValue && typeof userValue === 'object' && !Array.isArray(userValue)) {
        (merged as any)[key] = { ...(merged as any)[key], ...userValue };
      } else {
        (merged as any)[key] = userValue;
      }
    });
    
    return merged;
  }

  /**
   * Obtenir une valeur par chemin (ex: "api.timeout")
   */
  private getValueByPath(obj: any, path: string): any {
    return path.split('.').reduce((current, key) => {
      return current && current[key] !== undefined ? current[key] : undefined;
    }, obj);
  }

  /**
   * Définir une valeur par chemin
   */
  private setValueByPath(obj: any, path: string, value: any): void {
    const keys = path.split('.');
    const lastKey = keys.pop()!;
    const target = keys.reduce((current, key) => {
      if (!current[key] || typeof current[key] !== 'object') {
        current[key] = {};
      }
      return current[key];
    }, obj);
    target[lastKey] = value;
  }

  /**
   * Valider la configuration
   */
  validateConfiguration(config: Partial<AppConfiguration>): boolean {
    try {
      // Validation des URLs
      if (config.api?.baseUrl && !this.isValidUrl(config.api.baseUrl)) {
        console.error('URL API invalide:', config.api.baseUrl);
        return false;
      }
      
      if (config.api?.dataUrl && !this.isValidUrl(config.api.dataUrl)) {
        console.error('URL Data invalide:', config.api.dataUrl);
        return false;
      }
      
      // Validation des valeurs numériques
      if (config.api?.timeout && (config.api.timeout < 1000 || config.api.timeout > 300000)) {
        console.error('Timeout invalide (doit être entre 1000 et 300000ms):', config.api.timeout);
        return false;
      }
      
      if (config.cache?.maxSize && config.cache.maxSize < 1) {
        console.error('Taille de cache invalide:', config.cache.maxSize);
        return false;
      }
      
      return true;
    } catch (error) {
      console.error('Erreur lors de la validation de la configuration:', error);
      return false;
    }
  }

  /**
   * Vérifier si une URL est valide
   */
  private isValidUrl(url: string): boolean {
    try {
      new URL(url);
      return true;
    } catch {
      return false;
    }
  }

  /**
   * Nettoyage lors de la destruction
   */
  ngOnDestroy(): void {
    this.configuration.complete();
  }
}