import 'package:flutter/foundation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; const _kAccessToken = 'access_token'; const _kRefreshToken = 'refresh_token'; const _kUsername = 'username'; const _kRealName = 'real_name'; const _kShopNo = 'shop_no'; const _kShopId = 'shop_id'; const _kRole = 'role'; class AuthUser { final String accessToken; final String refreshToken; final String username; final String realName; final String shopNo; final int shopId; final String role; const AuthUser({ required this.accessToken, required this.refreshToken, required this.username, required this.realName, required this.shopNo, required this.shopId, this.role = 'operator', }); // Kept for ApiClient compatibility String get token => accessToken; } class AuthState { final AuthUser? user; final bool initialized; const AuthState({this.user, this.initialized = false}); bool get isLoggedIn => user != null; } class AuthNotifier extends StateNotifier { AuthNotifier() : super(const AuthState()); /// Called at app startup to restore persisted session. Future restore() async { try { final prefs = await SharedPreferences.getInstance(); final accessToken = prefs.getString(_kAccessToken); final refreshToken = prefs.getString(_kRefreshToken); final username = prefs.getString(_kUsername); final realName = prefs.getString(_kRealName); final shopNo = prefs.getString(_kShopNo); final shopIdStr = prefs.getString(_kShopId); final role = prefs.getString(_kRole); if (accessToken != null && refreshToken != null && username != null) { state = AuthState( initialized: true, user: AuthUser( accessToken: accessToken, refreshToken: refreshToken, username: username, realName: realName ?? username, shopNo: shopNo ?? '', shopId: int.tryParse(shopIdStr ?? '') ?? 0, role: role ?? 'operator', ), ); return; } } catch (_) { // Storage unavailable — fall through to logged-out state } state = const AuthState(initialized: true); } Future login(AuthUser user) async { debugPrint('[Auth] login() called, username=${user.username} shopId=${user.shopId}'); final prefs = await SharedPreferences.getInstance(); await prefs.setString(_kAccessToken, user.accessToken); await prefs.setString(_kRefreshToken, user.refreshToken); await prefs.setString(_kUsername, user.username); await prefs.setString(_kRealName, user.realName); await prefs.setString(_kShopNo, user.shopNo); await prefs.setString(_kShopId, user.shopId.toString()); await prefs.setString(_kRole, user.role); debugPrint('[Auth] login() setting state, token prefix: ${user.accessToken.substring(0, user.accessToken.length.clamp(0, 20))}...'); state = AuthState(initialized: true, user: user); debugPrint('[Auth] login() state set, isLoggedIn=${state.isLoggedIn}'); } void updateAccessToken(String newToken) { if (state.user == null) return; SharedPreferences.getInstance() .then((prefs) => prefs.setString(_kAccessToken, newToken)); state = AuthState( initialized: true, user: AuthUser( accessToken: newToken, refreshToken: state.user!.refreshToken, username: state.user!.username, realName: state.user!.realName, shopNo: state.user!.shopNo, shopId: state.user!.shopId, role: state.user!.role, ), ); } Future logout() async { debugPrint('[Auth] logout() called! stack: ${StackTrace.current}'); final prefs = await SharedPreferences.getInstance(); await prefs.remove(_kAccessToken); await prefs.remove(_kRefreshToken); await prefs.remove(_kUsername); await prefs.remove(_kRealName); await prefs.remove(_kShopNo); await prefs.remove(_kShopId); await prefs.remove(_kRole); state = const AuthState(initialized: true); } } final authStateProvider = StateNotifierProvider( (ref) => AuthNotifier(), );