/// Modèle complet de données pour un événement
/// Aligné avec le backend EvenementDTO
library evenement_model;

import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';

part 'evenement_model.g.dart';

/// Énumération des types d'événements
enum TypeEvenement {
  @JsonValue('ASSEMBLEE_GENERALE')
  assembleeGenerale,
  @JsonValue('REUNION')
  reunion,
  @JsonValue('FORMATION')
  formation,
  @JsonValue('CONFERENCE')
  conference,
  @JsonValue('ATELIER')
  atelier,
  @JsonValue('SEMINAIRE')
  seminaire,
  @JsonValue('EVENEMENT_SOCIAL')
  evenementSocial,
  @JsonValue('MANIFESTATION')
  manifestation,
  @JsonValue('CELEBRATION')
  celebration,
  @JsonValue('AUTRE')
  autre,
}

/// Énumération des statuts d'événements
enum StatutEvenement {
  @JsonValue('PLANIFIE')
  planifie,
  @JsonValue('CONFIRME')
  confirme,
  @JsonValue('EN_COURS')
  enCours,
  @JsonValue('TERMINE')
  termine,
  @JsonValue('ANNULE')
  annule,
  @JsonValue('REPORTE')
  reporte,
}

/// Énumération des priorités
enum PrioriteEvenement {
  @JsonValue('BASSE')
  basse,
  @JsonValue('MOYENNE')
  moyenne,
  @JsonValue('HAUTE')
  haute,
}

/// Modèle complet d'un événement
@JsonSerializable()
class EvenementModel extends Equatable {
  /// Identifiant unique
  final int? id;

  /// Titre de l'événement
  final String titre;

  /// Description détaillée
  final String? description;

  /// Date et heure de début
  @JsonKey(name: 'dateDebut')
  final DateTime dateDebut;

  /// Date et heure de fin
  @JsonKey(name: 'dateFin')
  final DateTime dateFin;

  /// Lieu de l'événement
  final String? lieu;

  /// Adresse complète
  final String? adresse;

  /// Ville
  final String? ville;

  /// Code postal
  @JsonKey(name: 'codePostal')
  final String? codePostal;

  /// Type d'événement
  final TypeEvenement type;

  /// Statut de l'événement
  final StatutEvenement statut;

  /// Nombre maximum de participants
  @JsonKey(name: 'maxParticipants')
  final int? maxParticipants;

  /// Nombre de participants actuels
  @JsonKey(name: 'participantsActuels')
  final int participantsActuels;

  /// ID de l'organisateur
  @JsonKey(name: 'organisateurId')
  final int? organisateurId;

  /// Nom de l'organisateur (pour affichage)
  @JsonKey(name: 'organisateurNom')
  final String? organisateurNom;

  /// ID de l'organisation
  @JsonKey(name: 'organisationId')
  final int? organisationId;

  /// Nom de l'organisation (pour affichage)
  @JsonKey(name: 'organisationNom')
  final String? organisationNom;

  /// Priorité de l'événement
  final PrioriteEvenement priorite;

  /// Événement public
  @JsonKey(name: 'estPublic')
  final bool estPublic;

  /// Inscription requise
  @JsonKey(name: 'inscriptionRequise')
  final bool inscriptionRequise;

  /// Coût de participation
  final double? cout;

  /// Devise
  final String devise;

  /// Tags/mots-clés
  final List<String> tags;

  /// URL de l'image
  @JsonKey(name: 'imageUrl')
  final String? imageUrl;

  /// URL du document
  @JsonKey(name: 'documentUrl')
  final String? documentUrl;

  /// Notes internes
  final String? notes;

  /// Date de création
  @JsonKey(name: 'dateCreation')
  final DateTime? dateCreation;

  /// Date de modification
  @JsonKey(name: 'dateModification')
  final DateTime? dateModification;

  /// Actif
  final bool actif;

  const EvenementModel({
    this.id,
    required this.titre,
    this.description,
    required this.dateDebut,
    required this.dateFin,
    this.lieu,
    this.adresse,
    this.ville,
    this.codePostal,
    this.type = TypeEvenement.autre,
    this.statut = StatutEvenement.planifie,
    this.maxParticipants,
    this.participantsActuels = 0,
    this.organisateurId,
    this.organisateurNom,
    this.organisationId,
    this.organisationNom,
    this.priorite = PrioriteEvenement.moyenne,
    this.estPublic = true,
    this.inscriptionRequise = false,
    this.cout,
    this.devise = 'XOF',
    this.tags = const [],
    this.imageUrl,
    this.documentUrl,
    this.notes,
    this.dateCreation,
    this.dateModification,
    this.actif = true,
  });

  /// Création depuis JSON
  factory EvenementModel.fromJson(Map<String, dynamic> json) =>
      _$EvenementModelFromJson(json);

  /// Conversion vers JSON
  Map<String, dynamic> toJson() => _$EvenementModelToJson(this);

  /// Copie avec modifications
  EvenementModel copyWith({
    int? id,
    String? titre,
    String? description,
    DateTime? dateDebut,
    DateTime? dateFin,
    String? lieu,
    String? adresse,
    String? ville,
    String? codePostal,
    TypeEvenement? type,
    StatutEvenement? statut,
    int? maxParticipants,
    int? participantsActuels,
    int? organisateurId,
    String? organisateurNom,
    int? organisationId,
    String? organisationNom,
    PrioriteEvenement? priorite,
    bool? estPublic,
    bool? inscriptionRequise,
    double? cout,
    String? devise,
    List<String>? tags,
    String? imageUrl,
    String? documentUrl,
    String? notes,
    DateTime? dateCreation,
    DateTime? dateModification,
    bool? actif,
  }) {
    return EvenementModel(
      id: id ?? this.id,
      titre: titre ?? this.titre,
      description: description ?? this.description,
      dateDebut: dateDebut ?? this.dateDebut,
      dateFin: dateFin ?? this.dateFin,
      lieu: lieu ?? this.lieu,
      adresse: adresse ?? this.adresse,
      ville: ville ?? this.ville,
      codePostal: codePostal ?? this.codePostal,
      type: type ?? this.type,
      statut: statut ?? this.statut,
      maxParticipants: maxParticipants ?? this.maxParticipants,
      participantsActuels: participantsActuels ?? this.participantsActuels,
      organisateurId: organisateurId ?? this.organisateurId,
      organisateurNom: organisateurNom ?? this.organisateurNom,
      organisationId: organisationId ?? this.organisationId,
      organisationNom: organisationNom ?? this.organisationNom,
      priorite: priorite ?? this.priorite,
      estPublic: estPublic ?? this.estPublic,
      inscriptionRequise: inscriptionRequise ?? this.inscriptionRequise,
      cout: cout ?? this.cout,
      devise: devise ?? this.devise,
      tags: tags ?? this.tags,
      imageUrl: imageUrl ?? this.imageUrl,
      documentUrl: documentUrl ?? this.documentUrl,
      notes: notes ?? this.notes,
      dateCreation: dateCreation ?? this.dateCreation,
      dateModification: dateModification ?? this.dateModification,
      actif: actif ?? this.actif,
    );
  }

  /// Durée de l'événement en heures
  double get dureeHeures {
    return dateFin.difference(dateDebut).inMinutes / 60.0;
  }

  /// Nombre de jours avant l'événement
  int get joursAvantEvenement {
    return dateDebut.difference(DateTime.now()).inDays;
  }

  /// Est dans le futur
  bool get estAVenir => dateDebut.isAfter(DateTime.now());

  /// Est en cours
  bool get estEnCours {
    final now = DateTime.now();
    return now.isAfter(dateDebut) && now.isBefore(dateFin);
  }

  /// Est passé
  bool get estPasse => dateFin.isBefore(DateTime.now());

  /// Places disponibles
  int? get placesDisponibles {
    if (maxParticipants == null) return null;
    return maxParticipants! - participantsActuels;
  }

  /// Est complet
  bool get estComplet {
    if (maxParticipants == null) return false;
    return participantsActuels >= maxParticipants!;
  }

  /// Peut s'inscrire
  bool get peutSinscrire {
    return estAVenir && 
           !estComplet && 
           statut == StatutEvenement.confirme &&
           inscriptionRequise;
  }

  @override
  List<Object?> get props => [
        id,
        titre,
        description,
        dateDebut,
        dateFin,
        lieu,
        adresse,
        ville,
        codePostal,
        type,
        statut,
        maxParticipants,
        participantsActuels,
        organisateurId,
        organisateurNom,
        organisationId,
        organisationNom,
        priorite,
        estPublic,
        inscriptionRequise,
        cout,
        devise,
        tags,
        imageUrl,
        documentUrl,
        notes,
        dateCreation,
        dateModification,
        actif,
      ];

  @override
  String toString() =>
      'EvenementModel(id: $id, titre: $titre, dateDebut: $dateDebut, statut: $statut)';
}

