import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:http/http.dart' as http; class AuthService extends ChangeNotifier { final _storage = const FlutterSecureStorage(); String? token; Map? profile; final _base = 'https://menuapi.devbeni.lol/api'; AuthService() { _loadToken(); } /// Convenience wrapper that returns the Data array for schedule or empty list Future> fetchSchedule(int year, int month) async { final resp = await _httpGet('/@me/schedule?year=$year&month=$month'); if (resp == null) return []; try { if (resp['data'] != null && resp['data']['Data'] is List) { return List.from(resp['data']['Data']); } } catch (e) { return []; } return []; } Future loadProfile() async { if (token == null) return; try { final res = await http.get( Uri.parse('https://menuapi.devbeni.lol/api/me'), headers: {'Authorization': 'Bearer $token'}, ); if (res.statusCode == 200) { final body = jsonDecode(res.body); // Try common shapes: { data: {...} } or { user: {...} } or the whole body if (body is Map && body['data'] is Map) profile = Map.from(body['data']); else if (body is Map && body['user'] is Map) profile = Map.from(body['user']); else if (body is Map && body['FullName'] != null) profile = Map.from(body); else profile = {'raw': body}; notifyListeners(); } else { if (kDebugMode) print('[AuthService] loadProfile failed ${res.statusCode}: ${res.body}'); } } catch (e) { if (kDebugMode) print('[AuthService] loadProfile error: $e'); } } Future login(String username, String password) async { try { final res = await http.post( Uri.parse('$_base/login'), headers: {'Content-Type': 'application/json'}, body: jsonEncode({'username': username, 'password': password}), ); if (res.statusCode != 200) return false; final data = jsonDecode(res.body); // token might be in different places; try common keys token = data['token'] ?? data['access_token'] ?? (data['data'] != null ? data['data']['token'] : null); if (token == null) return false; await _storage.write(key: 'token', value: token); await loadProfile(); notifyListeners(); return true; } catch (e) { return false; } } Future logout() async { token = null; profile = null; await _storage.delete(key: 'token'); notifyListeners(); } Future _httpGet(String path) async { if (token == null) { if (kDebugMode) print('[AuthService] _httpGet called without token for $path'); return null; } try { final res = await http.get(Uri.parse('$_base$path'), headers: {'Authorization': 'Bearer $token'}); if (res.statusCode == 200) { return jsonDecode(res.body); } else { if (kDebugMode) { print('[AuthService] GET $path -> ${res.statusCode}'); print('[AuthService] response body: ${res.body}'); } throw Exception('HTTP ${res.statusCode}'); } } catch (e) { if (kDebugMode) print('[AuthService] _httpGet error: $e'); rethrow; } } Future _loadToken() async { token = await _storage.read(key: 'token'); if (token != null) await loadProfile(); notifyListeners(); } }