import 'package:web/web.dart' as web;
import 'package:em2rp/config/api_config.dart';
import 'package:em2rp/utils/debug_log.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;

/// Service de Text-to-Speech utilisant Google Cloud TTS via Cloud Function
/// Avec système de cache pour optimiser les performances et réduire les coûts
class CloudTextToSpeechService {
  static final Map<String, String> _audioCache = {};
  static final Map<String, web.HTMLAudioElement> _audioPlayers = {};

  /// Générer l'audio TTS via Cloud Function
  /// Retourne l'URL de l'audio (mise en cache automatiquement côté serveur)
  static Future<String?> generateAudio(String text) async {
    try {
      // Vérifier le cache local d'abord
      if (_audioCache.containsKey(text)) {
        DebugLog.info('[CloudTTS] ✓ Local cache HIT: "${text.substring(0, 30)}..."');
        return _audioCache[text];
      }

      DebugLog.info('[CloudTTS] Generating audio for: "$text"');

      // Récupérer le token d'authentification
      final user = FirebaseAuth.instance.currentUser;
      if (user == null) {
        DebugLog.error('[CloudTTS] User not authenticated');
        return null;
      }

      final token = await user.getIdToken();
      if (token == null) {
        DebugLog.error('[CloudTTS] Failed to get auth token');
        return null;
      }

      // Préparer la requête
      final url = '${ApiConfig.baseUrl}/generateTTSV2';
      final headers = {
        'Authorization': 'Bearer $token',
        'Content-Type': 'application/json',
      };

      final body = json.encode({
        'data': {
          'text': text,
          'voiceConfig': {
            'languageCode': 'fr-FR',
            'name': 'fr-FR-Standard-B', // Voix masculine gratuite
            'ssmlGender': 'MALE',
          },
        },
      });

      DebugLog.info('[CloudTTS] Calling Cloud Function...');
      final startTime = DateTime.now();

      // Appeler la Cloud Function
      final response = await http.post(
        Uri.parse(url),
        headers: headers,
        body: body,
      );

      final duration = DateTime.now().difference(startTime).inMilliseconds;

      if (response.statusCode == 200) {
        final data = json.decode(response.body);
        final audioUrl = data['audioUrl'] as String?;
        final cached = data['cached'] as bool? ?? false;

      if (audioUrl != null) {
        // Mettre en cache localement
        _audioCache[text] = audioUrl;

        DebugLog.info('[CloudTTS] ✓ Audio generated - cached: $cached, duration: ${duration}ms');

        return audioUrl;
      }
      }

      DebugLog.error('[CloudTTS] Failed to generate audio', {
        'status': response.statusCode,
        'body': response.body,
      });

      return null;
    } catch (e) {
      DebugLog.error('[CloudTTS] Exception:', e);
      return null;
    }
  }

  /// Lire un audio depuis une URL
  static void playAudio(String audioUrl) {
    try {
      DebugLog.info('[CloudTTS] Playing audio...');

      // Créer ou réutiliser un HTMLAudioElement
      final player = _audioPlayers[audioUrl] ?? web.HTMLAudioElement();
      if (!_audioPlayers.containsKey(audioUrl)) {
        player.src = audioUrl;
        _audioPlayers[audioUrl] = player;
      }

      // Configurer le volume
      player.volume = 1.0;

      // Écouter les événements
      player.onEnded.listen((_) {
        DebugLog.info('[CloudTTS] ✓ Playback finished');
      });

      player.onError.listen((event) {
        DebugLog.error('[CloudTTS] ✗ Playback error:', event);
      });

      // Lire l'audio (pas de await avec package:web)
      player.play();

      DebugLog.info('[CloudTTS] ✓ Playback started');
    } catch (e) {
      DebugLog.error('[CloudTTS] Error playing audio:', e);
      rethrow;
    }
  }

  /// Générer et lire l'audio en une seule opération
  static Future<void> speak(String text) async {
    try {
      final audioUrl = await generateAudio(text);

      if (audioUrl != null) {
        playAudio(audioUrl);
      } else {
        DebugLog.error('[CloudTTS] Failed to generate audio for speech');
      }
    } catch (e) {
      DebugLog.error('[CloudTTS] Error in speak:', e);
      rethrow;
    }
  }

  /// Arrêter tous les audios en cours
  static void stopAll() {
    for (final player in _audioPlayers.values) {
      try {
        player.pause();
        player.currentTime = 0;
      } catch (e) {
        // Ignorer les erreurs de pause
      }
    }
    DebugLog.info('[CloudTTS] All players stopped');
  }

  /// Nettoyer le cache
  static void clearCache() {
    _audioCache.clear();
    _audioPlayers.clear();
    DebugLog.info('[CloudTTS] Cache cleared');
  }

  /// Pré-charger des audios fréquemment utilisés
  static Future<void> preloadCommonPhrases() async {
    final phrases = [
      'Équipement scanné',
      'Flight case',
      'Conteneur',
      'Validé',
      'Erreur',
    ];

    DebugLog.info('[CloudTTS] Preloading ${phrases.length} common phrases...');

    for (final phrase in phrases) {
      try {
        await generateAudio(phrase);
      } catch (e) {
        DebugLog.warning('[CloudTTS] Failed to preload: $phrase - $e');
      }
    }

    DebugLog.info('[CloudTTS] ✓ Preload complete');
  }
}

