import 'dart:convert'; import 'package:http/http.dart' as http; import '../models/models.dart'; class ApiService { String baseUrl; String? _token; ApiService({required this.baseUrl}); String? get token => _token; bool get isAuthenticated => _token != null; void setToken(String token) { _token = token; } Map get _headers => { if (_token != null) 'Authorization': 'Bearer $_token', 'Content-Type': 'application/json', 'Accept': 'application/json', }; Future login(String email, String password) async { final response = await http.post( Uri.parse('$baseUrl/api/v1/auth'), headers: {'Content-Type': 'application/json'}, body: jsonEncode({'email': email, 'password': password}), ); if (response.statusCode == 200) { final data = AuthResponse.fromJson(jsonDecode(response.body)); setToken(data.token); return data; } final body = jsonDecode(response.body); throw ApiException( statusCode: response.statusCode, message: body['error'] ?? 'Unknown error', ); } Future getApps() async { final response = await http.get( Uri.parse('$baseUrl/api/v1/apps'), headers: _headers, ); if (response.statusCode == 200) { return AppsResponse.fromJson(jsonDecode(response.body)); } if (response.statusCode == 401) { throw AuthException(); } final body = jsonDecode(response.body); throw ApiException( statusCode: response.statusCode, message: body['error'] ?? 'Unknown error', ); } Future downloadVersion(String versionId) async { final request = http.Request( 'GET', Uri.parse('$baseUrl/api/v1/versions/$versionId/download'), ); request.headers.addAll(_headers); final response = await http.Client().send(request); if (response.statusCode == 200) { return response; } if (response.statusCode == 401) { throw AuthException(); } response.stream.drain(); final body = await response.stream.bytesToString(); final parsed = jsonDecode(body); throw ApiException( statusCode: response.statusCode, message: parsed['error'] ?? 'Download failed', ); } String iconUrl(String iconPath) { if (iconPath.startsWith('http')) return iconPath; return '$baseUrl$iconPath'; } } class ApiException implements Exception { final int statusCode; final String message; ApiException({required this.statusCode, required this.message}); @override String toString() => message; } class AuthException implements Exception {}