import 'package:flutter/material.dart'; import 'package:wanisclient/config/AppSnackbar.dart'; import '../services/public_keys_service.dart'; class PublicKeysProvider extends ChangeNotifier { final PublicKeysService _service = PublicKeysService(); static final PublicKeysProvider _instance = PublicKeysProvider._internal(); factory PublicKeysProvider() { return _instance; } PublicKeysProvider._internal(); // ── loading state ───────────────────────────────────────────── bool _isLoading = false; bool _isLoaded = false; bool _isLoadingSecrets = false; String? _error; bool get isLoading => _isLoading; bool get isLoaded => _isLoaded; bool get isLoadingSecrets => _isLoadingSecrets; String? get error => _error; // ── public keys — available before login ────────────────────── String? mapboxToken; String? pubnubPublishKey; String? pubnubSubscribeKey; String? agoraAppId; String? recaptchaSiteKey; bool isTestEnvironment = false; // ── secret keys — available only after login ────────────────── String? googleMapKey; String? osmKey; String? pubnubSecretKey; String? agoraCertificate; String? recaptchaSecret; String? winsmsKey; String? winsmsSender; String? tunisiesmsKey; String? tunisiesmsSnder; String? twilioAuthToken; String? twilioAccountSid; String? twilioFromNo; String? twilioVerifySid; // ── missing keys check ──────────────────────────────────────── List get missingPublicKeys { final List missing = []; if (!_has(mapboxToken)) missing.add('Mapbox'); if (!_has(pubnubPublishKey)) missing.add('PubNub publish'); if (!_has(pubnubSubscribeKey)) missing.add('PubNub subscribe'); if (!_has(agoraAppId)) missing.add('Agora App ID'); return missing; } bool get allPublicKeysConfigured => missingPublicKeys.isEmpty; // ── load public keys — call at app startup ──────────────────── Future loadPublicKeys() async { if (_isLoading) return; _isLoading = true; _error = null; notifyListeners(); try { final keysResponse = await _service.fetchPublicKeys(); final profileResponse = await _service.fetchProfile(); if (keysResponse.data != null) { final data = keysResponse.data!; mapboxToken = _parse(data['mapbox']); pubnubPublishKey = _parse(data['pubnubpublic']); pubnubSubscribeKey = _parse(data['pubnubsubscribe']); agoraAppId = _parse(data['agoraid']); recaptchaSiteKey = _parse(data['recaptchasitekey']); } else { _error = keysResponse.errorMessage; } if (profileResponse.data != null) { isTestEnvironment = profileResponse.data!['isTest'] == true; } _isLoaded = true; } catch (e) { _error = e.toString(); } finally { _isLoading = false; notifyListeners(); } } // ── load secret keys — call right after login ───────────────── Future loadSecretKeys() async { if (_isLoadingSecrets) return; _isLoadingSecrets = true; notifyListeners(); try { final response = await _service.fetchSecretKeys(); if (response.data != null) { final data = response.data!; googleMapKey = _parse(data['googlemap']); osmKey = _parse(data['osm']); pubnubSecretKey = _parse(data['pubnubsecret']); agoraCertificate = _parse(data['agoracertificate']); recaptchaSecret = _parse(data['recaptcha']); winsmsKey = _parse(data['winsmskey']); winsmsSender = _parse(data['winsmssender']); tunisiesmsKey = _parse(data['tunisiesmskey']); tunisiesmsSnder = _parse(data['tunisiesmssender']); twilioAuthToken = _parse(data['twilioauthtoken']); twilioAccountSid = _parse(data['twilioaccountsid']); twilioFromNo = _parse(data['twiliofromo']); twilioVerifySid = _parse(data['twilioverifysid']); } } catch (e) { debugPrint('[PublicKeysProvider] loadSecretKeys error: $e'); } finally { _isLoadingSecrets = false; notifyListeners(); } } // ── clear secrets on logout ─────────────────────────────────── void clearSecretKeys() { googleMapKey = null; osmKey = null; pubnubSecretKey = null; agoraCertificate = null; recaptchaSecret = null; winsmsKey = null; winsmsSender = null; tunisiesmsKey = null; tunisiesmsSnder = null; twilioAuthToken = null; twilioAccountSid = null; twilioFromNo = null; twilioVerifySid = null; notifyListeners(); } // ── helpers ─────────────────────────────────────────────────── String? _parse(dynamic v) { if (v == null) return null; final s = v.toString().trim(); return s.isEmpty ? null : s; } bool _has(String? v) => v != null && v.isNotEmpty; } final publickeys = PublicKeysProvider(); extension PublicKeysGuard on PublicKeysProvider { bool guardKey(String? key, String keyName) { if (key == null || key.isEmpty) { AppSnackbar.showWarning("Keys", '⚠️ $keyName not configured'); debugPrint('[PublicKeysProvider] ⚠️ $keyName not configured'); return false; } return true; } }