import '../../domain/entities/reservation.dart';

/// Modèle de données pour les réservations (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 Reservation.
class ReservationModel {
  ReservationModel({
    required this.id,
    required this.userId,
    required this.userFullName,
    required this.eventId,
    required this.eventTitle,
    required this.reservationDate,
    required this.numberOfPeople,
    required this.status,
    this.establishmentId,
    this.establishmentName,
    this.notes,
    this.createdAt,
  });

  /// Factory pour créer un [ReservationModel] à partir d'un JSON.
  factory ReservationModel.fromJson(Map<String, dynamic> json) {
    return ReservationModel(
      id: _parseId(json, 'id', ''),
      userId: _parseId(json, 'userId', ''),
      userFullName: _parseString(json, 'userFullName', ''),
      eventId: _parseId(json, 'eventId', ''),
      eventTitle: _parseString(json, 'eventTitle', ''),
      reservationDate: _parseTimestamp(json['reservationDate']),
      numberOfPeople: _parseInt(json, 'numberOfPeople'),
      status: _parseStatus(json['status'] as String?),
      establishmentId: json['establishmentId'] as String?,
      establishmentName: json['establishmentName'] as String?,
      notes: json['notes'] as String?,
      createdAt: json['createdAt'] != null
          ? _parseTimestamp(json['createdAt'])
          : null,
    );
  }

  /// Crée un [ReservationModel] depuis une entité de domaine [Reservation].
  factory ReservationModel.fromEntity(Reservation reservation) {
    return ReservationModel(
      id: reservation.id,
      userId: reservation.userId,
      userFullName: reservation.userFullName,
      eventId: reservation.eventId,
      eventTitle: reservation.eventTitle,
      reservationDate: reservation.reservationDate,
      numberOfPeople: reservation.numberOfPeople,
      status: reservation.status,
      establishmentId: reservation.establishmentId,
      establishmentName: reservation.establishmentName,
      notes: reservation.notes,
      createdAt: reservation.createdAt,
    );
  }

  final String id;
  final String userId;
  final String userFullName;
  final String eventId;
  final String eventTitle;
  final DateTime reservationDate;
  final int numberOfPeople;
  final ReservationStatus status;
  final String? establishmentId;
  final String? establishmentName;
  final String? notes;
  final DateTime? createdAt;

  /// Convertit ce modèle en JSON pour l'envoi vers l'API.
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'userId': userId,
      'userFullName': userFullName,
      'eventId': eventId,
      'eventTitle': eventTitle,
      'reservationDate': reservationDate.toIso8601String(),
      'numberOfPeople': numberOfPeople,
      'status': _statusToString(status),
      if (establishmentId != null) 'establishmentId': establishmentId,
      if (establishmentName != null) 'establishmentName': establishmentName,
      if (notes != null) 'notes': notes,
      if (createdAt != null) 'createdAt': createdAt!.toIso8601String(),
    };
  }

  /// Convertit ce modèle vers une entité de domaine [Reservation].
  Reservation toEntity() {
    return Reservation(
      id: id,
      userId: userId,
      userFullName: userFullName,
      eventId: eventId,
      eventTitle: eventTitle,
      reservationDate: reservationDate,
      numberOfPeople: numberOfPeople,
      status: status,
      establishmentId: establishmentId,
      establishmentName: establishmentName,
      notes: notes,
      createdAt: createdAt,
    );
  }

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

  /// Parse une valeur int depuis le JSON avec valeur par défaut 1.
  static int _parseInt(Map<String, dynamic> json, String key) {
    return json[key] as int? ?? 1;
  }

  /// Parse un timestamp depuis le JSON.
  static DateTime _parseTimestamp(dynamic timestamp) {
    if (timestamp == null) return DateTime.now();

    if (timestamp is String) {
      try {
        return DateTime.parse(timestamp);
      } catch (e) {
        return DateTime.now();
      }
    }

    if (timestamp is int) {
      return DateTime.fromMillisecondsSinceEpoch(timestamp);
    }

    return DateTime.now();
  }

  /// Parse un ID (UUID) depuis le JSON.
  static String _parseId(
    Map<String, dynamic> json,
    String key,
    String defaultValue,
  ) {
    final value = json[key];
    if (value == null) return defaultValue;
    return value.toString();
  }

  /// Parse le statut de réservation depuis le JSON.
  static ReservationStatus _parseStatus(String? status) {
    if (status == null) return ReservationStatus.pending;

    switch (status.toLowerCase()) {
      case 'pending':
      case 'en attente':
        return ReservationStatus.pending;
      case 'confirmed':
      case 'confirmé':
      case 'confirmée':
        return ReservationStatus.confirmed;
      case 'cancelled':
      case 'annulé':
      case 'annulée':
        return ReservationStatus.cancelled;
      case 'completed':
      case 'terminé':
      case 'terminée':
        return ReservationStatus.completed;
      default:
        return ReservationStatus.pending;
    }
  }

  /// Convertit le statut en string pour l'API.
  static String _statusToString(ReservationStatus status) {
    switch (status) {
      case ReservationStatus.pending:
        return 'pending';
      case ReservationStatus.confirmed:
        return 'confirmed';
      case ReservationStatus.cancelled:
        return 'cancelled';
      case ReservationStatus.completed:
        return 'completed';
    }
  }
}
