// lib/remote/remote_http.dart import 'dart:developer' as dev; import 'package:flutter/services.dart'; import 'remote_settings.dart'; import 'auth_client.dart'; /// Helper HTTP per risorse remote (URL + headers di autenticazione). class RemoteHttp { static RemoteAuth? _auth; static String? _base; // Cache dell'ultimo set di header (mai null: {} se non autenticato) static Map _cachedHeaders = const {}; static Future? _initFuture; // evita init concorrenti /// Inizializza auth e base URL dai settings sicuri (robusto: non lancia). static Future init() { _initFuture ??= _doInit(); return _initFuture!; } static Future _doInit() async { try { final s = await RemoteSettings.load(); // safe lato storage final base = s.baseUrl.trim(); _base = base.isEmpty ? null : base; _auth = RemoteAuth(baseUrl: s.baseUrl, email: s.email, password: s.password); dev.log('[RemoteHttp] init: base=$_base, email=${s.email.isNotEmpty ? '***' : '(none)'}', name: 'RemoteHttp'); } catch (e, st) { dev.log('[RemoteHttp] init ERROR: $e', name: 'RemoteHttp', error: e, stackTrace: st); _auth = null; _base = null; } } /// Headers correnti (login on‑demand). Non lancia; ritorna {} se non disponibili. static Future> headers() async { if (_auth == null) { await init(); if (_auth == null) { _cachedHeaders = const {}; dev.log('[RemoteHttp] headers: init failed → NO TOKEN', name: 'RemoteHttp'); return _cachedHeaders; } } try { final h = await _auth!.authHeaders(); // login on-demand _cachedHeaders = Map.from(h); if ((_cachedHeaders['Authorization']?.isEmpty ?? true)) { dev.log('[RemoteHttp] headers: NO Authorization', name: 'RemoteHttp'); } else { dev.log('[RemoteHttp] headers: Authorization: Bearer ***', name: 'RemoteHttp'); } return _cachedHeaders; } on PlatformException catch (e, st) { // Tipico: secure storage/keystore corrotto → non rompiamo la UI dev.log('[RemoteHttp] headers PlatformException: $e → returning {}', name: 'RemoteHttp', error: e, stackTrace: st); _cachedHeaders = const {}; return _cachedHeaders; } catch (e, st) { dev.log('[RemoteHttp] headers ERROR: $e → returning {}', name: 'RemoteHttp', error: e, stackTrace: st); _cachedHeaders = const {}; return _cachedHeaders; } } /// Ultimi header noti (sincrono). Mai null; {} se non autenticato. static Map peekHeaders() => _cachedHeaders; /// Converte path relativo in assoluto. Se è già http/https lo ritorna com’è. static String absUrl(String? relativePath) { if (relativePath == null || relativePath.isEmpty) return ''; final lp = relativePath.trim().toLowerCase(); if (lp.startsWith('http://') || lp.startsWith('https://')) { return relativePath; } if (_base == null || _base!.isEmpty) return ''; final b = _base!.endsWith('/') ? _base! : '${_base!}/'; final rel = relativePath.startsWith('/') ? relativePath.substring(1) : relativePath; return '$b$rel'; } /// Facoltativo: warm‑up all’avvio per scaldare gli header. static Future warmUp() async { await init(); try { await headers(); } catch (_) { // già loggato in headers() } } /// Rilegge i settings a runtime (es. utente cambia base/email/password). static Future refreshFromSettings() async { _initFuture = null; await init(); _cachedHeaders = const {}; // saranno ricaricati al primo uso } }