import 'dart:convert';

import 'package:http/http.dart' as http;

/// Zentrale Quelle für ICE-Server (STUN/TURN), die in ALLE WebRTC-Verbindungen
/// injiziert werden (Matrix-1:1-Calls und LiveKit).
///
/// Hintergrund: Der Heimserver hängt hinter CGNAT (keine Portfreigabe möglich).
/// Direkte Verbindungen brauchen deshalb ICE-Hole-Punching mit STUN auf beiden
/// Seiten; für harte Fälle (symmetrische Mobilfunk-NAT) können später
/// TURN-Server (z. B. Cloudflare TURN, 1 TB/Monat gratis) ergänzt werden —
/// dafür muss nur die ice.json auf dem Pi aktualisiert werden, ohne App-Update.
class IceServers {
  /// Wird vom Pi ausgeliefert und kann dort per Cron mit frischen
  /// TURN-Credentials befüllt werden (siehe /home/steggi/matrix/ice.json).
  static const _remoteUrl =
      'https://steggi-matrix.work/.well-known/pyramid/ice.json';

  /// Fallback, falls die ice.json nicht erreichbar ist.
  static const List<Map<String, dynamic>> _fallback = [
    {
      'urls': [
        'stun:stun.l.google.com:19302',
        'stun:stun.cloudflare.com:3478',
      ],
    },
  ];

  static List<Map<String, dynamic>>? _cached;
  static DateTime? _fetchedAt;

  /// Liefert die ICE-Server als WebRTC-`iceServers`-Maps
  /// (`{'urls': [...], 'username': ..., 'credential': ...}`).
  /// Ergebnis wird 30 Minuten gecached; TURN-Credentials in der ice.json
  /// sollten deutlich länger gültig sein.
  static Future<List<Map<String, dynamic>>> get() async {
    final cached = _cached;
    if (cached != null &&
        _fetchedAt != null &&
        DateTime.now().difference(_fetchedAt!) <
            const Duration(minutes: 30)) {
      return cached;
    }
    try {
      final resp = await http
          .get(Uri.parse(_remoteUrl))
          .timeout(const Duration(seconds: 4));
      if (resp.statusCode == 200) {
        final body = jsonDecode(resp.body);
        final list = (body['ice_servers'] as List)
            .whereType<Map>()
            .map((e) => e.cast<String, dynamic>())
            .toList();
        if (list.isNotEmpty) {
          _cached = list;
          _fetchedAt = DateTime.now();
          return list;
        }
      }
    } catch (_) {
      // Offline/Endpoint fehlt — Fallback unten.
    }
    return _cached ?? _fallback;
  }
}
