import 'package:sysfarma_mobile/src/core/models/tenant_session.dart'; import 'package:sysfarma_mobile/src/core/observability/observability.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; final secureStorageProvider = Provider((ref) => const FlutterSecureStorage()); final tenantSessionStoreProvider = Provider( (ref) => TenantSessionStore(ref.watch(secureStorageProvider)), ); /// Emite cambios de sesión activa. Cualquier screen puede watch-earlo /// para reaccionar a login/logout/cambio de rol. final currentSessionProvider = FutureProvider((ref) async { final store = ref.watch(tenantSessionStoreProvider); return store.readSession(); }); class TenantSessionStore { const TenantSessionStore(this._storage); static const _baseUrlKey = 'tenant.base_url'; static const _tokenKey = 'tenant.api_token'; static const _companyNameKey = 'tenant.company_name'; static const _rucKey = 'tenant.ruc'; static const _userTypeKey = 'tenant.user_type'; static const _activeEstablishmentIdKey = 'tenant.active_establishment_id'; final FlutterSecureStorage _storage; Future saveSession(TenantSession session) async { await _storage.write(key: _baseUrlKey, value: session.baseUrl); await _storage.write(key: _tokenKey, value: session.token); await _storage.write(key: _companyNameKey, value: session.companyName ?? ''); await _storage.write(key: _rucKey, value: session.ruc ?? ''); await _storage.write(key: _userTypeKey, value: session.userType ?? ''); await _storage.write( key: _activeEstablishmentIdKey, value: session.activeEstablishmentId?.toString() ?? '', ); await Observability.setSessionContext(session); } Future readSession() async { final baseUrl = await _storage.read(key: _baseUrlKey); final token = await _storage.read(key: _tokenKey); if (baseUrl == null || token == null || baseUrl.isEmpty || token.isEmpty) { const testMode = bool.fromEnvironment('MOBILE_WEB_TEST_MODE', defaultValue: false); if (kIsWeb && testMode) { return const TenantSession( baseUrl: 'http://demo.enterfarmaplus.test', token: 'mock-token', companyName: 'Demo', ruc: '00000000000', userType: 'admin', ); } return null; } final companyName = await _storage.read(key: _companyNameKey); final ruc = await _storage.read(key: _rucKey); final userType = await _storage.read(key: _userTypeKey); final activeEstablishmentIdRaw = await _storage.read(key: _activeEstablishmentIdKey); final activeEstablishmentId = int.tryParse(activeEstablishmentIdRaw ?? ''); return TenantSession( baseUrl: baseUrl, token: token, companyName: companyName, ruc: (ruc != null && ruc.isNotEmpty) ? ruc : null, userType: (userType != null && userType.isNotEmpty) ? userType : null, activeEstablishmentId: activeEstablishmentId, ); } Future readRuc() async { final ruc = await _storage.read(key: _rucKey); return (ruc != null && ruc.isNotEmpty) ? ruc : null; } /// Lee los datos de tenant (RUC, baseUrl, companyName) aunque no exista /// token activo. Útil para prellenar login después de logout. Future<({String? ruc, String? baseUrl, String? companyName})> readTenantConfig() async { final ruc = await _storage.read(key: _rucKey); final baseUrl = await _storage.read(key: _baseUrlKey); final companyName = await _storage.read(key: _companyNameKey); return ( ruc: (ruc != null && ruc.isNotEmpty) ? ruc : null, baseUrl: (baseUrl != null && baseUrl.isNotEmpty) ? baseUrl : null, companyName: (companyName != null && companyName.isNotEmpty) ? companyName : null, ); } /// Logout "suave": borra solo credenciales, conserva tenant (RUC, baseUrl, /// companyName) para que la próxima pantalla de login ya venga prellenada. Future clear() async { await _storage.delete(key: _tokenKey); await _storage.delete(key: _userTypeKey); await _storage.delete(key: _activeEstablishmentIdKey); await Observability.clearSessionContext(); } /// Logout "duro": borra todo, incluyendo el tenant. Útil para cambiar de /// empresa. Future clearAll() async { await _storage.delete(key: _baseUrlKey); await _storage.delete(key: _tokenKey); await _storage.delete(key: _companyNameKey); await _storage.delete(key: _rucKey); await _storage.delete(key: _userTypeKey); await _storage.delete(key: _activeEstablishmentIdKey); await Observability.clearSessionContext(); } }