import 'dart:async'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import '../models/user.dart'; import 'api_client.dart'; class AuthService { final ApiClient _api; final FlutterSecureStorage _storage = const FlutterSecureStorage(); Timer? _refreshTimer; AuthService(this._api); Future login(String serverUrl, String username, String password, {String? fcmToken}) async { await _api.setBaseUrl(serverUrl); final response = await _api.dio.post('/auth/login', data: { 'username': username, 'password': password, if (fcmToken != null) 'fcm_token': fcmToken, }); final data = response.data; if (data['success'] != true) { throw Exception(data['message'] ?? 'Login failed'); } await _storage.write(key: 'access_token', value: data['access_token']); await _storage.write(key: 'refresh_token', value: data['refresh_token']); _scheduleRefresh(data['expires_in'] as int? ?? 3600); return User.fromJson(data['user']); } Future tryRestoreSession() async { final token = await _storage.read(key: 'access_token'); if (token == null) return false; await _api.restoreBaseUrl(); if (_api.dio.options.baseUrl.isEmpty) return false; try { final response = await _api.dio.get('/agent/status'); return response.statusCode == 200; } catch (_) { return false; } } Future refreshToken() async { final refreshToken = await _storage.read(key: 'refresh_token'); if (refreshToken == null) throw Exception('No refresh token'); final response = await _api.dio.post('/auth/refresh', data: { 'refresh_token': refreshToken, }); final data = response.data; if (data['success'] != true) { throw Exception('Token refresh failed'); } await _storage.write(key: 'access_token', value: data['access_token']); if (data['refresh_token'] != null) { await _storage.write(key: 'refresh_token', value: data['refresh_token']); } _scheduleRefresh(data['expires_in'] as int? ?? 3600); } void _scheduleRefresh(int expiresInSeconds) { _refreshTimer?.cancel(); // Refresh 2 minutes before expiry final refreshIn = Duration(seconds: expiresInSeconds - 120); if (refreshIn.isNegative) return; _refreshTimer = Timer(refreshIn, () async { try { await refreshToken(); } catch (_) {} }); } Future logout() async { _refreshTimer?.cancel(); try { await _api.dio.post('/auth/logout'); } catch (_) {} await _storage.deleteAll(); } void dispose() { _refreshTimer?.cancel(); } }