import '../../core/constants/env_config.dart';
import '../../core/utils/app_logger.dart';
import '../../domain/entities/user.dart';

/// Modèle de données pour les utilisateurs (Data Transfer Object).
///
/// Cette classe est responsable de la sérialisation/désérialisation
/// avec l'API backend et convertit vers/depuis l'entité de domaine [User].
///
/// **Usage:**
/// ```dart
/// // Depuis JSON
/// final user = UserModel.fromJson(jsonData);
///
/// // Vers JSON
/// final json = user.toJson();
///
/// // Vers entité de domaine
/// final entity = user.toEntity();
/// ```
class UserModel extends User {
  /// Crée une nouvelle instance de [UserModel].
  ///
  /// [userId] L'identifiant unique de l'utilisateur
  /// [userLastName] Le nom de famille de l'utilisateur
  /// [userFirstName] Le prénom de l'utilisateur
  /// [email] L'adresse email de l'utilisateur
  /// [motDePasse] Le mot de passe (hashé côté serveur)
  /// [profileImageUrl] L'URL de l'image de profil
  /// [eventsCount] Le nombre d'événements créés (optionnel)
  /// [friendsCount] Le nombre d'amis (optionnel)
  /// [postsCount] Le nombre de posts (optionnel)
  /// [visitedPlacesCount] Le nombre de lieux visités (optionnel)
  const UserModel({
    required super.userId,
    required super.userLastName,
    required super.userFirstName,
    required super.email,
    required super.motDePasse,
    required super.profileImageUrl,
    super.isVerified,
    super.eventsCount,
    super.friendsCount,
    super.postsCount,
    super.visitedPlacesCount,
  });

  /// Crée un [UserModel] à partir d'un JSON reçu depuis l'API.
  ///
  /// [json] Les données JSON à parser
  ///
  /// Returns un [UserModel] avec les données parsées
  ///
  /// **Note:** Les valeurs par défaut sont utilisées si des champs sont manquants.
  ///
  /// **Exemple:**
  /// ```dart
  /// final json = {
  ///   'userId': '123',
  ///   'nom': 'Doe',
  ///   'prenoms': 'John',
  ///   'email': 'john@example.com',
  /// };
  /// final user = UserModel.fromJson(json);
  /// ```
  factory UserModel.fromJson(Map<String, dynamic> json) {
    try {
      // Le backend peut renvoyer 'uuid' ou 'userId', on accepte les deux
      final userId = _parseString(json, 'userId', '') != ''
          ? _parseString(json, 'userId', '')
          : _parseString(json, 'uuid', '');
      
      return UserModel(
        userId: userId.isNotEmpty ? userId : (json['uuid']?.toString() ?? json['userId']?.toString() ?? ''),
        userLastName: _parseString(json, 'nom', 'Inconnu'),
        userFirstName: _parseString(json, 'prenoms', 'Inconnu'),
        email: _parseString(json, 'email', ''),
        motDePasse: _parseString(json, 'motDePasse', ''),
        profileImageUrl: _parseString(json, 'profileImageUrl', ''),
        isVerified: json['isVerified'] as bool? ?? false,
        eventsCount: _parseInt(json, 'eventsCount') ?? 0,
        friendsCount: _parseInt(json, 'friendsCount') ?? 0,
        postsCount: _parseInt(json, 'postsCount') ?? 0,
        visitedPlacesCount: _parseInt(json, 'visitedPlacesCount') ?? 0,
      );
    } catch (e, stackTrace) {
      AppLogger.e('Erreur lors du parsing JSON', error: e, stackTrace: stackTrace, tag: 'UserModel');
      rethrow;
    }
  }

  /// Parse une valeur string depuis le JSON avec valeur par défaut.
  static String _parseString(
    Map<String, dynamic> json,
    String key,
    String defaultValue,
  ) {
    final value = json[key];
    if (value == null) return defaultValue;
    return value.toString();
  }

  /// Parse une valeur int depuis le JSON (optionnel).
  static int? _parseInt(Map<String, dynamic> json, String key) {
    final value = json[key];
    if (value == null) return null;
    if (value is int) return value;
    if (value is String) {
      return int.tryParse(value);
    }
    return null;
  }

  /// Convertit ce [UserModel] en JSON pour l'envoi vers l'API.
  ///
  /// Returns une [Map] contenant les données de l'utilisateur
  ///
  /// **Note:** Le mot de passe est envoyé en clair (hashé côté serveur).
  ///
  /// **Exemple:**
  /// ```dart
  /// final user = UserModel(...);
  /// final json = user.toJson();
  /// // Envoyer json à l'API
  /// ```
  @override
  Map<String, dynamic> toJson() {
    final json = <String, dynamic>{
      if (userId.isNotEmpty) 'id': userId,
      'nom': userLastName,
      'prenoms': userFirstName,
      'email': email,
      if (motDePasse.isNotEmpty) 'motDePasse': motDePasse,
      if (profileImageUrl.isNotEmpty) 'profileImageUrl': profileImageUrl,
    };

    // Ajouter les compteurs optionnels s'ils sont présents
    if (eventsCount != null) {
      json['eventsCount'] = eventsCount;
    }
    if (friendsCount != null) {
      json['friendsCount'] = friendsCount;
    }
    if (postsCount != null) {
      json['postsCount'] = postsCount;
    }
    if (visitedPlacesCount != null) {
      json['visitedPlacesCount'] = visitedPlacesCount;
    }

    return json;
  }

  /// Convertit ce modèle vers une entité de domaine [User].
  ///
  /// Returns une instance de [User] avec les mêmes données
  ///
  /// **Exemple:**
  /// ```dart
  /// final model = UserModel.fromJson(json);
  /// final entity = model.toEntity();
  /// ```
  User toEntity() {
    return User(
      userId: userId,
      userLastName: userLastName,
      userFirstName: userFirstName,
      email: email,
      motDePasse: motDePasse,
      profileImageUrl: profileImageUrl,
      eventsCount: eventsCount,
      friendsCount: friendsCount,
      postsCount: postsCount,
      visitedPlacesCount: visitedPlacesCount,
    );
  }

  /// Crée une copie de ce [UserModel] avec des valeurs modifiées.
  ///
  /// Tous les paramètres sont optionnels. Seuls les paramètres fournis
  /// seront modifiés dans la nouvelle instance.
  ///
  /// **Exemple:**
  /// ```dart
  /// final updated = user.copyWith(
  ///   userFirstName: 'Jane',
  ///   profileImageUrl: 'https://example.com/new-image.jpg',
  /// );
  /// ```
  UserModel copyWith({
    String? userId,
    String? userLastName,
    String? userFirstName,
    String? email,
    String? motDePasse,
    String? profileImageUrl,
    int? eventsCount,
    int? friendsCount,
    int? postsCount,
    int? visitedPlacesCount,
  }) {
    return UserModel(
      userId: userId ?? this.userId,
      userLastName: userLastName ?? this.userLastName,
      userFirstName: userFirstName ?? this.userFirstName,
      email: email ?? this.email,
      motDePasse: motDePasse ?? this.motDePasse,
      profileImageUrl: profileImageUrl ?? this.profileImageUrl,
      eventsCount: eventsCount ?? this.eventsCount,
      friendsCount: friendsCount ?? this.friendsCount,
      postsCount: postsCount ?? this.postsCount,
      visitedPlacesCount: visitedPlacesCount ?? this.visitedPlacesCount,
    );
  }

  @override
  String toString() {
    return 'UserModel('
        'userId: $userId, '
        'name: $userFirstName $userLastName, '
        'email: $email'
        ')';
  }
}
