// lib/remote/remote_db_uris.dart import 'dart:convert'; class RemoteDbUris { // Schema personalizzato che non attiva ContentResolver. static const _scheme = 'aves-remote'; static const _hostRemoteId = 'rid'; static const _hostRemotePath = 'path'; static const _hostAnon = 'anon'; /// Costruisce un URI fittizio univoco e stabile per un elemento remoto. /// /// Priorità: /// 1. remoteId, se presente /// 2. remotePath, se presente /// 3. anon, fallback estremo non stabile /// /// Esempi: /// - `aves-remote://rid/` /// - `aves-remote://path/` /// - `aves-remote://anon/` static String make({String? remoteId, String? remotePath}) { final rid = remoteId?.trim(); if (rid != null && rid.isNotEmpty) { return '$_scheme://$_hostRemoteId/${Uri.encodeComponent(rid)}'; } final path = remotePath?.trim(); if (path != null && path.isNotEmpty) { final b64 = base64Url.encode(utf8.encode(path)); return '$_scheme://$_hostRemotePath/$b64'; } // Estremo fallback, pochissimo probabile. // Nota: non è stabile tra sync diversi, quindi non usarlo se puoi evitarlo. return '$_scheme://$_hostAnon/${DateTime.now().microsecondsSinceEpoch}'; } /// Riconosce se un URI è fittizio remoto. static bool isSynthetic(String? uri) { if (uri == null) return false; final raw = uri.trim(); if (raw.isEmpty) return false; final parsed = Uri.tryParse(raw); return parsed != null && parsed.scheme == _scheme; } /// Estrae il remoteId da un URI remoto sintetico. /// /// Formato supportato: /// `aves-remote://rid/` /// /// Esempio: /// `aves-remote://rid/f46da4...` /// /// Ritorna: /// `f46da4...` static String? remoteIdFromUri(String? uri) { final parsed = _tryParseSynthetic(uri); if (parsed == null) return null; if (parsed.host != _hostRemoteId) return null; if (parsed.pathSegments.isEmpty) return null; final rid = Uri.decodeComponent(parsed.pathSegments.first).trim(); return rid.isEmpty ? null : rid; } /// Estrae il remotePath da un URI remoto sintetico. /// /// Formato supportato: /// `aves-remote://path/` static String? remotePathFromUri(String? uri) { final parsed = _tryParseSynthetic(uri); if (parsed == null) return null; if (parsed.host != _hostRemotePath) return null; if (parsed.pathSegments.isEmpty) return null; final encoded = parsed.pathSegments.first.trim(); if (encoded.isEmpty) return null; try { return utf8.decode(base64Url.decode(encoded)).trim(); } catch (_) { return null; } } /// Ritorna true se l'URI contiene un remoteId estraibile. static bool hasRemoteId(String? uri) { return remoteIdFromUri(uri) != null; } /// Ritorna true se l'URI contiene un remotePath estraibile. static bool hasRemotePath(String? uri) { return remotePathFromUri(uri) != null; } /// Ricostruisce una URI canonica partendo da una URI esistente. /// /// Utile se in futuro vuoi normalizzare formati vecchi. /// /// Per ora: /// - se contiene remoteId, rigenera da remoteId; /// - se contiene remotePath, rigenera da remotePath; /// - altrimenti ritorna l'URI originale se sintetica; /// - altrimenti null. static String? normalize(String? uri) { if (!isSynthetic(uri)) return null; final rid = remoteIdFromUri(uri); if (rid != null && rid.isNotEmpty) { return make(remoteId: rid); } final path = remotePathFromUri(uri); if (path != null && path.isNotEmpty) { return make(remotePath: path); } final raw = uri?.trim(); return raw == null || raw.isEmpty ? null : raw; } /// Helper interno: parse sicuro solo per URI sintetiche remote. static Uri? _tryParseSynthetic(String? uri) { if (uri == null) return null; final raw = uri.trim(); if (raw.isEmpty) return null; final parsed = Uri.tryParse(raw); if (parsed == null) return null; if (parsed.scheme != _scheme) return null; return parsed; } }