/// Domain Entity: UserInfo
///
/// Represents complete user information fetched from the API.
/// This is a plain Dart class matching the app's entity pattern.
library;

import 'package:worker/core/database/models/enums.dart';

/// UserInfo Entity
///
/// Contains all user account information including:
/// - Personal details (name, email, phone, CCCD)
/// - Role and status
/// - Loyalty program data (tier, points)
/// - Company information
/// - ERPNext integration data
class UserInfo {
  /// Unique user identifier (name field from ERPNext)
  final String userId;

  /// Full name
  final String fullName;

  /// Email address
  final String? email;

  /// Phone number
  final String? phoneNumber;

  /// User role
  final UserRole role;

  /// Account status
  final UserStatus status;

  /// Current loyalty tier
  final LoyaltyTier loyaltyTier;

  /// Total loyalty points earned (lifetime)
  final int totalPoints;

  /// Available points for redemption
  final int availablePoints;

  /// Points expiring soon
  final int expiringPoints;

  /// Avatar image URL
  final String? avatarUrl;

  /// Company name
  final String? companyName;

  /// Tax identification number
  final String? taxId;

  /// Address
  final String? address;

  /// CCCD/ID card number
  final String? cccd;

  /// Date of birth
  final DateTime? dateOfBirth;

  /// Gender
  final String? gender;

  /// ID card front image URL
  final String? idCardFront;

  /// ID card back image URL
  final String? idCardBack;

  /// Certificate image URLs
  final List<String> certificates;

  /// Membership verification status text
  final String? membershipStatus;

  /// Membership status color indicator
  final String? membershipStatusColor;

  /// Whether user is verified
  final bool isVerified;

  /// Whether to display credential verification form
  final bool credentialDisplay;

  /// Referral code
  final String? referralCode;

  /// ERPNext customer ID
  final String? erpnextCustomerId;

  /// Account creation timestamp
  final DateTime createdAt;

  /// Last update timestamp
  final DateTime updatedAt;

  const UserInfo({
    required this.userId,
    required this.fullName,
    this.email,
    this.phoneNumber,
    required this.role,
    required this.status,
    required this.loyaltyTier,
    required this.totalPoints,
    required this.availablePoints,
    required this.expiringPoints,
    this.avatarUrl,
    this.companyName,
    this.taxId,
    this.address,
    this.cccd,
    this.dateOfBirth,
    this.gender,
    this.idCardFront,
    this.idCardBack,
    this.certificates = const [],
    this.membershipStatus,
    this.membershipStatusColor,
    this.isVerified = false,
    this.credentialDisplay = false,
    this.referralCode,
    this.erpnextCustomerId,
    required this.createdAt,
    required this.updatedAt,
  });

  /// Check if user is active
  bool get isActive => status == UserStatus.active;

  /// Check if user is pending approval
  bool get isPending => status == UserStatus.pending;

  /// Check if user has company info
  bool get hasCompanyInfo =>
      companyName != null && companyName!.isNotEmpty;

  /// Get user initials for avatar fallback
  String get initials {
    final nameParts = fullName.trim().split(' ');
    if (nameParts.isEmpty) return '?';
    if (nameParts.length == 1) {
      return nameParts[0].substring(0, 1).toUpperCase();
    }
    // First letter of first name + first letter of last name
    return '${nameParts.first.substring(0, 1)}${nameParts.last.substring(0, 1)}'
        .toUpperCase();
  }

  /// Get tier display name
  String get tierDisplayName {
    switch (loyaltyTier) {
      case LoyaltyTier.titan:
        return 'Titan';
      case LoyaltyTier.diamond:
        return 'Diamond';
      case LoyaltyTier.platinum:
        return 'Platinum';
      case LoyaltyTier.gold:
        return 'Gold';
      case LoyaltyTier.silver:
        return 'Silver';
      case LoyaltyTier.bronze:
        return 'Bronze';
    }
  }

  /// Copy with method for immutability
  UserInfo copyWith({
    String? userId,
    String? fullName,
    String? email,
    String? phoneNumber,
    UserRole? role,
    UserStatus? status,
    LoyaltyTier? loyaltyTier,
    int? totalPoints,
    int? availablePoints,
    int? expiringPoints,
    String? avatarUrl,
    String? companyName,
    String? taxId,
    String? address,
    String? cccd,
    DateTime? dateOfBirth,
    String? gender,
    String? idCardFront,
    String? idCardBack,
    List<String>? certificates,
    String? membershipStatus,
    String? membershipStatusColor,
    bool? isVerified,
    bool? credentialDisplay,
    String? referralCode,
    String? erpnextCustomerId,
    DateTime? createdAt,
    DateTime? updatedAt,
  }) {
    return UserInfo(
      userId: userId ?? this.userId,
      fullName: fullName ?? this.fullName,
      email: email ?? this.email,
      phoneNumber: phoneNumber ?? this.phoneNumber,
      role: role ?? this.role,
      status: status ?? this.status,
      loyaltyTier: loyaltyTier ?? this.loyaltyTier,
      totalPoints: totalPoints ?? this.totalPoints,
      availablePoints: availablePoints ?? this.availablePoints,
      expiringPoints: expiringPoints ?? this.expiringPoints,
      avatarUrl: avatarUrl ?? this.avatarUrl,
      companyName: companyName ?? this.companyName,
      taxId: taxId ?? this.taxId,
      address: address ?? this.address,
      cccd: cccd ?? this.cccd,
      dateOfBirth: dateOfBirth ?? this.dateOfBirth,
      gender: gender ?? this.gender,
      idCardFront: idCardFront ?? this.idCardFront,
      idCardBack: idCardBack ?? this.idCardBack,
      certificates: certificates ?? this.certificates,
      membershipStatus: membershipStatus ?? this.membershipStatus,
      membershipStatusColor: membershipStatusColor ?? this.membershipStatusColor,
      isVerified: isVerified ?? this.isVerified,
      credentialDisplay: credentialDisplay ?? this.credentialDisplay,
      referralCode: referralCode ?? this.referralCode,
      erpnextCustomerId: erpnextCustomerId ?? this.erpnextCustomerId,
      createdAt: createdAt ?? this.createdAt,
      updatedAt: updatedAt ?? this.updatedAt,
    );
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is UserInfo &&
        other.userId == userId &&
        other.fullName == fullName &&
        other.email == email &&
        other.phoneNumber == phoneNumber &&
        other.role == role &&
        other.status == status &&
        other.loyaltyTier == loyaltyTier &&
        other.totalPoints == totalPoints &&
        other.availablePoints == availablePoints &&
        other.expiringPoints == expiringPoints &&
        other.avatarUrl == avatarUrl &&
        other.companyName == companyName &&
        other.taxId == taxId &&
        other.address == address &&
        other.cccd == cccd &&
        other.referralCode == referralCode &&
        other.erpnextCustomerId == erpnextCustomerId;
  }

  @override
  int get hashCode {
    return Object.hash(
      userId,
      fullName,
      email,
      phoneNumber,
      role,
      status,
      loyaltyTier,
      totalPoints,
      availablePoints,
      expiringPoints,
      avatarUrl,
      companyName,
      taxId,
      address,
      cccd,
      referralCode,
      erpnextCustomerId,
    );
  }

  @override
  String toString() {
    return 'UserInfo(userId: $userId, fullName: $fullName, '
        'role: $role, status: $status, loyaltyTier: $loyaltyTier, '
        'totalPoints: $totalPoints, availablePoints: $availablePoints)';
  }
}
