import '../../domain/entities/auth_user.dart'; /// Modelo de datos que extiende la entidad [AuthUser]. /// Responsable de serialización/deserialización JSON. /// En la fase MVP el token se simula localmente (sin llamada real a backend). class AuthUserModel extends AuthUser { const AuthUserModel({ required super.token, required super.email, required super.role, required super.issuedAt, required super.expiresAt, }); factory AuthUserModel.fromJson(Map json) { return AuthUserModel( token: json['token'] as String, email: json['email'] as String, role: json['role'] as String? ?? 'citizen', issuedAt: DateTime.parse(json['issued_at'] as String), expiresAt: DateTime.parse(json['expires_at'] as String), ); } Map toJson() { return { 'token': token, 'email': email, 'role': role, 'issued_at': issuedAt.toIso8601String(), 'expires_at': expiresAt.toIso8601String(), }; } /// Crea un token JWT simulado para la fase MVP. /// En producción este token vendría del backend con firma RS256. factory AuthUserModel.simulatedJwt({ required String email, required String role, }) { final now = DateTime.now(); // Header.Payload.Signature — simulado con base64 simple final header = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9'; final payloadRaw = '{"sub":"usr_${email.hashCode.abs()}","email":"$email","role":"$role",' '"iat":${now.millisecondsSinceEpoch},' '"exp":${now.add(const Duration(hours: 8)).millisecondsSinceEpoch},' '"iss":"waste-notify-mvp"}'; // ignore: deprecated_member_use final payload = _base64UrlEncode(payloadRaw); const signature = 'SIMULATED_SIGNATURE_MVP'; return AuthUserModel( token: '$header.$payload.$signature', email: email, role: role, issuedAt: now, expiresAt: now.add(const Duration(hours: 8)), ); } static String _base64UrlEncode(String input) { final bytes = input.codeUnits; final encoded = bytes .map((b) => b.toRadixString(16).padLeft(2, '0')) .join(); return encoded.substring(0, encoded.length > 64 ? 64 : encoded.length); } }