import 'package:equatable/equatable.dart'; import '../../core/utils/unit_conversion_utils.dart'; class User extends Equatable { final String id; final String username; final String email; final String? avatarUrl; final String? bio; final bool isPublicProfile; final String? twitterHandle; final String? instagramHandle; final String? tiktokHandle; final String? websiteUrl; final DateTime? countdownStartDate; final DateTime? countdownEndDate; final Gender? gender; final DateTime? birthDate; final int? storedAge; final double? heightCm; final double? weightKg; final HeightUnit heightUnit; final WeightUnit weightUnit; final DateTime createdAt; final DateTime updatedAt; const User({ required this.id, required this.username, required this.email, this.avatarUrl, this.bio, this.isPublicProfile = false, this.twitterHandle, this.instagramHandle, this.tiktokHandle, this.websiteUrl, this.countdownStartDate, this.countdownEndDate, this.gender, this.birthDate, this.storedAge, this.heightCm, this.weightKg, this.heightUnit = HeightUnit.metric, this.weightUnit = WeightUnit.metric, required this.createdAt, required this.updatedAt, }); bool get hasCountdownStarted => countdownStartDate != null; bool get isCountdownActive { if (!hasCountdownStarted || countdownEndDate == null) return false; return DateTime.now().isBefore(countdownEndDate!); } int? get daysRemaining { if (!isCountdownActive) return null; return countdownEndDate!.difference(DateTime.now()).inDays; } int? get age { if (storedAge != null) return storedAge; if (birthDate == null) return null; return UnitConversionUtils.calculateAge(birthDate!); } String get formattedHeight { if (heightCm == null) return ''; return UnitConversionUtils.formatHeight(heightCm!, heightUnit); } String get formattedWeight { if (weightKg == null) return ''; return UnitConversionUtils.formatWeight(weightKg!, weightUnit); } double? get bmi { if (heightCm == null || weightKg == null) return null; return UnitConversionUtils.calculateBmi(weightKg!, heightCm!); } String get bmiCategory { final bmiValue = bmi; if (bmiValue == null) return ''; return UnitConversionUtils.getBmiCategory(bmiValue); } User copyWith({ String? id, String? username, String? email, String? avatarUrl, String? bio, bool? isPublicProfile, String? twitterHandle, String? instagramHandle, String? tiktokHandle, String? websiteUrl, DateTime? countdownStartDate, DateTime? countdownEndDate, Gender? gender, DateTime? birthDate, int? storedAge, double? heightCm, double? weightKg, HeightUnit? heightUnit, WeightUnit? weightUnit, DateTime? createdAt, DateTime? updatedAt, }) { return User( id: id ?? this.id, username: username ?? this.username, email: email ?? this.email, avatarUrl: avatarUrl ?? this.avatarUrl, bio: bio ?? this.bio, isPublicProfile: isPublicProfile ?? this.isPublicProfile, twitterHandle: twitterHandle ?? this.twitterHandle, instagramHandle: instagramHandle ?? this.instagramHandle, tiktokHandle: tiktokHandle ?? this.tiktokHandle, websiteUrl: websiteUrl ?? this.websiteUrl, countdownStartDate: countdownStartDate ?? this.countdownStartDate, countdownEndDate: countdownEndDate ?? this.countdownEndDate, gender: gender ?? this.gender, birthDate: birthDate ?? this.birthDate, storedAge: storedAge ?? this.storedAge, heightCm: heightCm ?? this.heightCm, weightKg: weightKg ?? this.weightKg, heightUnit: heightUnit ?? this.heightUnit, weightUnit: weightUnit ?? this.weightUnit, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt, ); } @override List get props => [ id, username, email, avatarUrl, bio, isPublicProfile, twitterHandle, instagramHandle, tiktokHandle, websiteUrl, countdownStartDate, countdownEndDate, gender, birthDate, storedAge, heightCm, weightKg, heightUnit, weightUnit, createdAt, updatedAt, ]; Map toJson() { return { 'id': id, 'username': username, 'email': email, 'avatar_url': avatarUrl, 'bio': bio, 'is_public_profile': isPublicProfile, 'twitter_handle': twitterHandle, 'instagram_handle': instagramHandle, 'tiktok_handle': tiktokHandle, 'website_url': websiteUrl, 'countdown_start_date': countdownStartDate?.toIso8601String(), 'countdown_end_date': countdownEndDate?.toIso8601String(), 'gender': gender?.toDatabaseString(), 'birth_date': birthDate?.toIso8601String().split('T').first, 'age': storedAge, 'height_cm': heightCm, 'weight_kg': weightKg, 'height_unit': heightUnit.code, 'weight_unit': weightUnit.code, 'created_at': createdAt.toIso8601String(), 'updated_at': updatedAt.toIso8601String(), }; } factory User.fromJson(Map json) { return User( id: json['id'] as String, username: json['username'] as String, email: json['email'] as String, avatarUrl: json['avatar_url'] as String?, bio: json['bio'] as String?, isPublicProfile: json['is_public_profile'] as bool? ?? false, twitterHandle: json['twitter_handle'] as String?, instagramHandle: json['instagram_handle'] as String?, tiktokHandle: json['tiktok_handle'] as String?, websiteUrl: json['website_url'] as String?, countdownStartDate: json['countdown_start_date'] != null ? DateTime.parse(json['countdown_start_date'] as String) : null, countdownEndDate: json['countdown_end_date'] != null ? DateTime.parse(json['countdown_end_date'] as String) : null, gender: json['gender'] != null ? Gender.fromString(json['gender'] as String) : null, birthDate: json['birth_date'] != null ? DateTime.parse(json['birth_date'] as String) : null, storedAge: json['age'] as int?, heightCm: json['height_cm'] as double?, weightKg: json['weight_kg'] as double?, heightUnit: json['height_unit'] != null ? HeightUnit.values.firstWhere((unit) => unit.code == json['height_unit']) : HeightUnit.metric, weightUnit: json['weight_unit'] != null ? WeightUnit.values.firstWhere((unit) => unit.code == json['weight_unit']) : WeightUnit.metric, createdAt: DateTime.parse(json['created_at'] as String), updatedAt: DateTime.parse(json['updated_at'] as String), ); } }