/// Modèle de données pour les organisations
/// Correspond au OrganizationDTO du backend
library organization_model;

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

part 'organization_model.g.dart';

/// Énumération des types d'organisation
enum TypeOrganization {
  @JsonValue('ASSOCIATION')
  association,
  @JsonValue('COOPERATIVE')
  cooperative,
  @JsonValue('LIONS_CLUB')
  lionsClub,
  @JsonValue('ENTREPRISE')
  entreprise,
  @JsonValue('ONG')
  ong,
  @JsonValue('FONDATION')
  fondation,
  @JsonValue('SYNDICAT')
  syndicat,
  @JsonValue('AUTRE')
  autre,
}

/// Énumération des statuts d'organisation
enum StatutOrganization {
  @JsonValue('ACTIVE')
  active,
  @JsonValue('INACTIVE')
  inactive,
  @JsonValue('SUSPENDUE')
  suspendue,
  @JsonValue('DISSOUTE')
  dissoute,
  @JsonValue('EN_CREATION')
  enCreation,
}

/// Extension pour les types d'organisation
extension TypeOrganizationExtension on TypeOrganization {
  String get displayName {
    switch (this) {
      case TypeOrganization.association:
        return 'Association';
      case TypeOrganization.cooperative:
        return 'Coopérative';
      case TypeOrganization.lionsClub:
        return 'Lions Club';
      case TypeOrganization.entreprise:
        return 'Entreprise';
      case TypeOrganization.ong:
        return 'ONG';
      case TypeOrganization.fondation:
        return 'Fondation';
      case TypeOrganization.syndicat:
        return 'Syndicat';
      case TypeOrganization.autre:
        return 'Autre';
    }
  }

  String get icon {
    switch (this) {
      case TypeOrganization.association:
        return '🏛️';
      case TypeOrganization.cooperative:
        return '🤝';
      case TypeOrganization.lionsClub:
        return '🦁';
      case TypeOrganization.entreprise:
        return '🏢';
      case TypeOrganization.ong:
        return '🌍';
      case TypeOrganization.fondation:
        return '🏛️';
      case TypeOrganization.syndicat:
        return '⚖️';
      case TypeOrganization.autre:
        return '📋';
    }
  }
}

/// Extension pour les statuts d'organisation
extension StatutOrganizationExtension on StatutOrganization {
  String get displayName {
    switch (this) {
      case StatutOrganization.active:
        return 'Active';
      case StatutOrganization.inactive:
        return 'Inactive';
      case StatutOrganization.suspendue:
        return 'Suspendue';
      case StatutOrganization.dissoute:
        return 'Dissoute';
      case StatutOrganization.enCreation:
        return 'En création';
    }
  }

  String get color {
    switch (this) {
      case StatutOrganization.active:
        return '#10B981'; // Vert
      case StatutOrganization.inactive:
        return '#6B7280'; // Gris
      case StatutOrganization.suspendue:
        return '#F59E0B'; // Orange
      case StatutOrganization.dissoute:
        return '#EF4444'; // Rouge
      case StatutOrganization.enCreation:
        return '#3B82F6'; // Bleu
    }
  }
}

/// Énumération des types de tri pour les organisations
enum OrganizationSortType {
  name,
  creationDate,
  memberCount,
  type,
  status,
}

/// Extension pour les types de tri d'organisation
extension OrganizationSortTypeExtension on OrganizationSortType {
  String get displayName {
    switch (this) {
      case OrganizationSortType.name:
        return 'Nom';
      case OrganizationSortType.creationDate:
        return 'Date de création';
      case OrganizationSortType.memberCount:
        return 'Nombre de membres';
      case OrganizationSortType.type:
        return 'Type';
      case OrganizationSortType.status:
        return 'Statut';
    }
  }
}

/// Modèle d'organisation mobile
@JsonSerializable()
class OrganizationModel extends Equatable {
  /// Identifiant unique
  final String? id;

  /// Nom de l'organisation
  final String nom;

  /// Nom court ou sigle
  final String? nomCourt;

  /// Type d'organisation
  @JsonKey(name: 'typeOrganisation')
  final TypeOrganization typeOrganisation;

  /// Statut de l'organisation
  final StatutOrganization statut;

  /// Description
  final String? description;

  /// Date de fondation
  @JsonKey(name: 'dateFondation')
  final DateTime? dateFondation;

  /// Numéro d'enregistrement officiel
  @JsonKey(name: 'numeroEnregistrement')
  final String? numeroEnregistrement;

  /// Email de contact
  final String? email;

  /// Téléphone
  final String? telephone;

  /// Site web
  @JsonKey(name: 'siteWeb')
  final String? siteWeb;

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

  /// Ville
  final String? ville;

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

  /// Région
  final String? region;

  /// Pays
  final String? pays;

  /// Logo URL
  final String? logo;

  /// Nombre de membres
  @JsonKey(name: 'nombreMembres')
  final int nombreMembres;

  /// Nombre d'administrateurs
  @JsonKey(name: 'nombreAdministrateurs')
  final int nombreAdministrateurs;

  /// Nombre d'événements (fourni par l'API si disponible)
  @JsonKey(name: 'nombreEvenements')
  final int? nombreEvenements;

  /// Budget annuel
  @JsonKey(name: 'budgetAnnuel')
  final double? budgetAnnuel;

  /// Devise
  final String devise;

  /// Cotisation obligatoire
  @JsonKey(name: 'cotisationObligatoire')
  final bool cotisationObligatoire;

  /// Montant cotisation annuelle
  @JsonKey(name: 'montantCotisationAnnuelle')
  final double? montantCotisationAnnuelle;

  /// Objectifs
  final String? objectifs;

  /// Activités principales
  @JsonKey(name: 'activitesPrincipales')
  final String? activitesPrincipales;

  /// Certifications
  final String? certifications;

  /// Partenaires
  final String? partenaires;

  /// Organisation publique
  @JsonKey(name: 'organisationPublique')
  final bool organisationPublique;

  /// Accepte nouveaux membres
  @JsonKey(name: 'accepteNouveauxMembres')
  final bool accepteNouveauxMembres;

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

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

  /// Actif
  final bool actif;

  const OrganizationModel({
    this.id,
    required this.nom,
    this.nomCourt,
    this.typeOrganisation = TypeOrganization.association,
    this.statut = StatutOrganization.active,
    this.description,
    this.dateFondation,
    this.numeroEnregistrement,
    this.email,
    this.telephone,
    this.siteWeb,
    this.adresse,
    this.ville,
    this.codePostal,
    this.region,
    this.pays,
    this.logo,
    this.nombreMembres = 0,
    this.nombreAdministrateurs = 0,
    this.nombreEvenements,
    this.budgetAnnuel,
    this.devise = 'XOF',
    this.cotisationObligatoire = false,
    this.montantCotisationAnnuelle,
    this.objectifs,
    this.activitesPrincipales,
    this.certifications,
    this.partenaires,
    this.organisationPublique = true,
    this.accepteNouveauxMembres = true,
    this.dateCreation,
    this.dateModification,
    this.actif = true,
  });

  /// Factory depuis JSON
  factory OrganizationModel.fromJson(Map<String, dynamic> json) =>
      _$OrganizationModelFromJson(json);

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

  /// Copie avec modifications
  OrganizationModel copyWith({
    String? id,
    String? nom,
    String? nomCourt,
    TypeOrganization? typeOrganisation,
    StatutOrganization? statut,
    String? description,
    DateTime? dateFondation,
    String? numeroEnregistrement,
    String? email,
    String? telephone,
    String? siteWeb,
    String? adresse,
    String? ville,
    String? codePostal,
    String? region,
    String? pays,
    String? logo,
    int? nombreMembres,
    int? nombreAdministrateurs,
    int? nombreEvenements,
    double? budgetAnnuel,
    String? devise,
    bool? cotisationObligatoire,
    double? montantCotisationAnnuelle,
    String? objectifs,
    String? activitesPrincipales,
    String? certifications,
    String? partenaires,
    bool? organisationPublique,
    bool? accepteNouveauxMembres,
    DateTime? dateCreation,
    DateTime? dateModification,
    bool? actif,
  }) {
    return OrganizationModel(
      id: id ?? this.id,
      nom: nom ?? this.nom,
      nomCourt: nomCourt ?? this.nomCourt,
      typeOrganisation: typeOrganisation ?? this.typeOrganisation,
      statut: statut ?? this.statut,
      description: description ?? this.description,
      dateFondation: dateFondation ?? this.dateFondation,
      numeroEnregistrement: numeroEnregistrement ?? this.numeroEnregistrement,
      email: email ?? this.email,
      telephone: telephone ?? this.telephone,
      siteWeb: siteWeb ?? this.siteWeb,
      adresse: adresse ?? this.adresse,
      ville: ville ?? this.ville,
      codePostal: codePostal ?? this.codePostal,
      region: region ?? this.region,
      pays: pays ?? this.pays,
      logo: logo ?? this.logo,
      nombreMembres: nombreMembres ?? this.nombreMembres,
      nombreAdministrateurs: nombreAdministrateurs ?? this.nombreAdministrateurs,
      nombreEvenements: nombreEvenements ?? this.nombreEvenements,
      budgetAnnuel: budgetAnnuel ?? this.budgetAnnuel,
      devise: devise ?? this.devise,
      cotisationObligatoire: cotisationObligatoire ?? this.cotisationObligatoire,
      montantCotisationAnnuelle: montantCotisationAnnuelle ?? this.montantCotisationAnnuelle,
      objectifs: objectifs ?? this.objectifs,
      activitesPrincipales: activitesPrincipales ?? this.activitesPrincipales,
      certifications: certifications ?? this.certifications,
      partenaires: partenaires ?? this.partenaires,
      organisationPublique: organisationPublique ?? this.organisationPublique,
      accepteNouveauxMembres: accepteNouveauxMembres ?? this.accepteNouveauxMembres,
      dateCreation: dateCreation ?? this.dateCreation,
      dateModification: dateModification ?? this.dateModification,
      actif: actif ?? this.actif,
    );
  }

  /// Ancienneté en années
  int get ancienneteAnnees {
    if (dateFondation == null) return 0;
    return DateTime.now().difference(dateFondation!).inDays ~/ 365;
  }

  /// Adresse complète formatée
  String get adresseComplete {
    final parts = <String>[];
    if (adresse?.isNotEmpty == true) parts.add(adresse!);
    if (ville?.isNotEmpty == true) parts.add(ville!);
    if (codePostal?.isNotEmpty == true) parts.add(codePostal!);
    if (region?.isNotEmpty == true) parts.add(region!);
    if (pays?.isNotEmpty == true) parts.add(pays!);
    return parts.join(', ');
  }

  /// Nom d'affichage
  String get nomAffichage => nomCourt?.isNotEmpty == true ? '$nomCourt ($nom)' : nom;

  @override
  List<Object?> get props => [
        id,
        nom,
        nomCourt,
        typeOrganisation,
        statut,
        description,
        dateFondation,
        numeroEnregistrement,
        email,
        telephone,
        siteWeb,
        adresse,
        ville,
        codePostal,
        region,
        pays,
        logo,
        nombreMembres,
        nombreAdministrateurs,
        nombreEvenements,
        budgetAnnuel,
        devise,
        cotisationObligatoire,
        montantCotisationAnnuelle,
        objectifs,
        activitesPrincipales,
        certifications,
        partenaires,
        organisationPublique,
        accepteNouveauxMembres,
        dateCreation,
        dateModification,
        actif,
      ];

  @override
  String toString() => 'OrganisationModel(id: $id, nom: $nom, type: $typeOrganisation, statut: $statut)';
}
