/// User Info Model
///
/// Data model for user information from API.
/// Handles JSON serialization and conversion to domain entity.
library;

import 'package:worker/core/database/models/enums.dart';
import 'package:worker/features/account/domain/entities/user_info.dart';

/// User Info Model
///
/// Maps API response from get_user_info endpoint to UserInfo entity.
class UserInfoModel {
  const UserInfoModel({
    required this.userId,
    required this.fullName,
    this.email,
    this.phoneNumber,
    required this.role,
    required this.status,
    required this.loyaltyTier,
    this.totalPoints = 0,
    this.availablePoints = 0,
    this.expiringPoints = 0,
    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,
    this.createdAt,
    this.updatedAt,
  });

  final String userId;
  final String fullName;
  final String? email;
  final String? phoneNumber;
  final UserRole role;
  final UserStatus status;
  final LoyaltyTier loyaltyTier;
  final int totalPoints;
  final int availablePoints;
  final int expiringPoints;
  final String? avatarUrl;
  final String? companyName;
  final String? taxId;
  final String? address;
  final String? cccd;
  final DateTime? dateOfBirth;
  final String? gender;
  final String? idCardFront;
  final String? idCardBack;
  final List<String> certificates;
  final String? membershipStatus;
  final String? membershipStatusColor;
  final bool isVerified;
  final bool credentialDisplay;
  final String? referralCode;
  final String? erpnextCustomerId;
  final DateTime? createdAt;
  final DateTime? updatedAt;

  // =========================================================================
  // JSON SERIALIZATION
  // =========================================================================

  /// Create UserInfoModel from API JSON response
  ///
  /// Expected API response structure:
  /// ```json
  /// {
  ///   "message": {
  ///     "user_id": "...",
  ///     "full_name": "...",
  ///     "email": "...",
  ///     "phone_number": "...",
  ///     "role": "customer",
  ///     "status": "active",
  ///     "loyalty_tier": "gold",
  ///     "total_points": 1000,
  ///     "available_points": 800,
  ///     "expiring_points": 200,
  ///     "avatar_url": "...",
  ///     "company_name": "...",
  ///     "tax_id": "...",
  ///     "address": "...",
  ///     "cccd": "...",
  ///     "referral_code": "...",
  ///     "erpnext_customer_id": "...",
  ///     "created_at": "...",
  ///     "updated_at": "...",
  ///     "last_login_at": "..."
  ///   }
  /// }
  /// ```
  factory UserInfoModel.fromJson(Map<String, dynamic> json) {
    // API response structure: { "message": { "full_name": "...", ... } }
    // Data is directly under 'message', not nested in 'data'
    final data = json['message'] as Map<String, dynamic>? ?? json;

    return UserInfoModel(
      // Use email as userId since API doesn't provide user_id
      userId: data['email'] as String? ?? data['phone'] as String? ?? 'unknown',
      fullName: data['full_name'] as String? ?? '',
      email: data['email'] as String?,
      phoneNumber: data['phone'] as String?,
      // Default values for fields not in this API
      role: UserRole.customer, // Default to customer
      status: UserStatus.active, // Default to active
      loyaltyTier: LoyaltyTier.bronze, // Default to bronze
      totalPoints: 0,
      availablePoints: 0,
      expiringPoints: 0,
      avatarUrl: data['avatar'] as String?,
      companyName: data['company_name'] as String?,
      taxId: data['tax_code'] as String?,
      address: data['address'] as String?,
      cccd: null, // CCCD number not in API
      dateOfBirth: _parseDateTime(data['date_of_birth'] as String?),
      gender: data['gender'] as String?,
      idCardFront: data['id_card_front'] as String?,
      idCardBack: data['id_card_back'] as String?,
      certificates: (data['certificates'] as List<dynamic>?)
          ?.map((e) => e.toString())
          .toList() ?? const [],
      membershipStatus: data['membership_status'] as String?,
      membershipStatusColor: data['membership_status_color'] as String?,
      isVerified: data['is_verified'] as bool? ?? false,
      credentialDisplay: data['credential_display'] as bool? ?? false,
      referralCode: null,
      erpnextCustomerId: null,
      createdAt: DateTime.now(),
      updatedAt: DateTime.now(),
    );
  }

  /// Convert UserInfoModel to JSON
  Map<String, dynamic> toJson() {
    return {
      'user_id': userId,
      'full_name': fullName,
      'email': email,
      'phone_number': phoneNumber,
      'role': role.name,
      'status': status.name,
      'loyalty_tier': loyaltyTier.name,
      'total_points': totalPoints,
      'available_points': availablePoints,
      'expiring_points': expiringPoints,
      'avatar_url': avatarUrl,
      'company_name': companyName,
      'tax_id': taxId,
      'address': address,
      'cccd': cccd,
      'referral_code': referralCode,
      'erpnext_customer_id': erpnextCustomerId,
      'created_at': createdAt?.toIso8601String(),
      'updated_at': updatedAt?.toIso8601String(),
    };
  }

  // =========================================================================
  // DOMAIN CONVERSION
  // =========================================================================

  /// Convert to domain entity
  UserInfo toEntity() {
    final now = DateTime.now();
    return UserInfo(
      userId: userId,
      fullName: fullName,
      email: email,
      phoneNumber: phoneNumber,
      role: role,
      status: status,
      loyaltyTier: loyaltyTier,
      totalPoints: totalPoints,
      availablePoints: availablePoints,
      expiringPoints: expiringPoints,
      avatarUrl: avatarUrl,
      companyName: companyName,
      taxId: taxId,
      address: address,
      cccd: cccd,
      dateOfBirth: dateOfBirth,
      gender: gender,
      idCardFront: idCardFront,
      idCardBack: idCardBack,
      certificates: certificates,
      membershipStatus: membershipStatus,
      membershipStatusColor: membershipStatusColor,
      isVerified: isVerified,
      credentialDisplay: credentialDisplay,
      referralCode: referralCode,
      erpnextCustomerId: erpnextCustomerId,
      createdAt: createdAt ?? now,
      updatedAt: updatedAt ?? now,
    );
  }

  /// Create model from domain entity
  factory UserInfoModel.fromEntity(UserInfo entity) {
    return UserInfoModel(
      userId: entity.userId,
      fullName: entity.fullName,
      email: entity.email,
      phoneNumber: entity.phoneNumber,
      role: entity.role,
      status: entity.status,
      loyaltyTier: entity.loyaltyTier,
      totalPoints: entity.totalPoints,
      availablePoints: entity.availablePoints,
      expiringPoints: entity.expiringPoints,
      avatarUrl: entity.avatarUrl,
      companyName: entity.companyName,
      taxId: entity.taxId,
      address: entity.address,
      cccd: entity.cccd,
      referralCode: entity.referralCode,
      erpnextCustomerId: entity.erpnextCustomerId,
      createdAt: entity.createdAt,
      updatedAt: entity.updatedAt,
    );
  }

  // =========================================================================
  // HELPER METHODS
  // =========================================================================

  /// Parse user role from string
  static UserRole _parseUserRole(String? role) {
    if (role == null) return UserRole.customer;

    return UserRole.values.firstWhere(
      (e) => e.name.toLowerCase() == role.toLowerCase(),
      orElse: () => UserRole.customer,
    );
  }

  /// Parse user status from string
  static UserStatus _parseUserStatus(String? status) {
    if (status == null) return UserStatus.pending;

    // Handle ERPNext status values
    final normalizedStatus = status.toLowerCase();
    if (normalizedStatus == 'enabled' || normalizedStatus == 'active') {
      return UserStatus.active;
    }
    if (normalizedStatus == 'disabled' || normalizedStatus == 'inactive') {
      return UserStatus.suspended;
    }

    return UserStatus.values.firstWhere(
      (e) => e.name.toLowerCase() == normalizedStatus,
      orElse: () => UserStatus.pending,
    );
  }

  /// Parse loyalty tier from string
  static LoyaltyTier _parseLoyaltyTier(String? tier) {
    if (tier == null) return LoyaltyTier.bronze;

    return LoyaltyTier.values.firstWhere(
      (e) => e.name.toLowerCase() == tier.toLowerCase(),
      orElse: () => LoyaltyTier.bronze,
    );
  }

  /// Parse integer from dynamic value
  static int _parseInt(dynamic value) {
    if (value == null) return 0;
    if (value is int) return value;
    if (value is double) return value.toInt();
    if (value is String) return int.tryParse(value) ?? 0;
    return 0;
  }

  /// Parse DateTime from string
  static DateTime? _parseDateTime(String? dateString) {
    if (dateString == null || dateString.isEmpty) return null;
    try {
      return DateTime.parse(dateString);
    } catch (e) {
      return null;
    }
  }

  // =========================================================================
  // EQUALITY
  // =========================================================================

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

    return other is UserInfoModel && other.userId == userId;
  }

  @override
  int get hashCode => userId.hashCode;

  @override
  String toString() {
    return 'UserInfoModel(userId: $userId, fullName: $fullName, '
        'tier: $loyaltyTier, points: $totalPoints)';
  }
}
