import 'package:cloud_firestore/cloud_firestore.dart';

/// Modèle représentant une activité touristique liée à un voyage
class Activity {
  final String id;
  final String tripId;
  final String name;
  final String description;
  final String category;
  final String? imageUrl;
  final double? rating;
  final String? priceLevel;
  final String? address;
  final double? latitude;
  final double? longitude;
  final String? placeId; // Google Places ID
  final String? website;
  final String? phoneNumber;
  final List<String> openingHours;
  final Map<String, int> votes; // userId -> vote (1 pour pour, -1 pour contre)
  final DateTime createdAt;
  final DateTime updatedAt;
  final DateTime? date; // Date prévue pour l'activité
  final String? createdBy; // ID de l'utilisateur qui a créé l'activité

  Activity({
    required this.id,
    required this.tripId,
    required this.name,
    required this.description,
    required this.category,
    this.imageUrl,
    this.rating,
    this.priceLevel,
    this.address,
    this.latitude,
    this.longitude,
    this.placeId,
    this.website,
    this.phoneNumber,
    this.openingHours = const [],
    this.votes = const {},
    required this.createdAt,
    required this.updatedAt,
    this.date,
    this.createdBy,
  });

  /// Calcule le score total des votes
  int get totalVotes {
    return votes.values.fold(0, (total, vote) => total + vote);
  }

  /// Calcule le nombre de votes positifs
  int get positiveVotes {
    return votes.values.where((vote) => vote > 0).length;
  }

  /// Calcule le nombre de votes négatifs
  int get negativeVotes {
    return votes.values.where((vote) => vote < 0).length;
  }

  /// Vérifie si l'utilisateur a voté
  bool hasUserVoted(String userId) {
    return votes.containsKey(userId);
  }

  /// Récupère le vote d'un utilisateur (-1, 0, 1)
  int getUserVote(String userId) {
    return votes[userId] ?? 0;
  }

  /// Vérifie si tous les participants du voyage ont voté positivement pour cette activité
  bool isApprovedByAllParticipants(List<String> tripParticipants) {
    if (tripParticipants.isEmpty) return false;

    // Tous les participants doivent avoir voté
    for (String participantId in tripParticipants) {
      if (!votes.containsKey(participantId)) {
        return false; // Quelqu'un n'a pas encore voté
      }
      if (votes[participantId] != 1) {
        return false; // Quelqu'un a voté négativement ou neutre
      }
    }

    return true; // Tous ont voté positivement
  }

  /// Crée une copie avec des modifications
  Activity copyWith({
    String? id,
    String? tripId,
    String? name,
    String? description,
    String? category,
    String? imageUrl,
    double? rating,
    String? priceLevel,
    String? address,
    double? latitude,
    double? longitude,
    String? placeId,
    String? website,
    String? phoneNumber,
    List<String>? openingHours,
    Map<String, int>? votes,
    DateTime? createdAt,
    DateTime? updatedAt,
    DateTime? date,
    bool clearDate = false,
    String? createdBy,
  }) {
    return Activity(
      id: id ?? this.id,
      tripId: tripId ?? this.tripId,
      name: name ?? this.name,
      description: description ?? this.description,
      category: category ?? this.category,
      imageUrl: imageUrl ?? this.imageUrl,
      rating: rating ?? this.rating,
      priceLevel: priceLevel ?? this.priceLevel,
      address: address ?? this.address,
      latitude: latitude ?? this.latitude,
      longitude: longitude ?? this.longitude,
      placeId: placeId ?? this.placeId,
      website: website ?? this.website,
      phoneNumber: phoneNumber ?? this.phoneNumber,
      openingHours: openingHours ?? this.openingHours,
      votes: votes ?? this.votes,
      createdAt: createdAt ?? this.createdAt,
      updatedAt: updatedAt ?? this.updatedAt,
      date: clearDate ? null : (date ?? this.date),
      createdBy: createdBy ?? this.createdBy,
    );
  }

  /// Conversion vers Map pour Firestore
  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'tripId': tripId,
      'name': name,
      'description': description,
      'category': category,
      'imageUrl': imageUrl,
      'rating': rating,
      'priceLevel': priceLevel,
      'address': address,
      'latitude': latitude,
      'longitude': longitude,
      'placeId': placeId,
      'website': website,
      'phoneNumber': phoneNumber,
      'openingHours': openingHours,
      'votes': votes,
      'createdAt': Timestamp.fromDate(createdAt),
      'updatedAt': Timestamp.fromDate(updatedAt),
      'date': date != null ? Timestamp.fromDate(date!) : null,
      'createdBy': createdBy,
    };
  }

  /// Création depuis Map Firestore
  factory Activity.fromMap(Map<String, dynamic> map) {
    return Activity(
      id: map['id'] ?? '',
      tripId: map['tripId'] ?? '',
      name: map['name'] ?? '',
      description: map['description'] ?? '',
      category: map['category'] ?? '',
      imageUrl: map['imageUrl'],
      rating: map['rating']?.toDouble(),
      priceLevel: map['priceLevel'],
      address: map['address'],
      latitude: map['latitude']?.toDouble(),
      longitude: map['longitude']?.toDouble(),
      placeId: map['placeId'],
      website: map['website'],
      phoneNumber: map['phoneNumber'],
      openingHours: List<String>.from(map['openingHours'] ?? []),
      votes: Map<String, int>.from(map['votes'] ?? {}),
      createdAt: (map['createdAt'] as Timestamp).toDate(),
      updatedAt: (map['updatedAt'] as Timestamp).toDate(),
      date: map['date'] != null ? (map['date'] as Timestamp).toDate() : null,
      createdBy: map['createdBy'],
    );
  }

  /// Création depuis snapshot Firestore
  factory Activity.fromSnapshot(DocumentSnapshot snapshot) {
    final data = snapshot.data() as Map<String, dynamic>;
    return Activity.fromMap({...data, 'id': snapshot.id});
  }

  @override
  String toString() {
    return 'Activity(id: $id, name: $name, category: $category, votes: $totalVotes)';
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    return other is Activity && other.id == id;
  }

  @override
  int get hashCode => id.hashCode;
}

/// Énumération des catégories d'activités
enum ActivityCategory {
  museum('Musée', 'museum'),
  restaurant('Restaurant', 'restaurant'),
  attraction('Attraction', 'tourist_attraction'),
  entertainment('Divertissement', 'amusement_park'),
  shopping('Shopping', 'shopping_mall'),
  nature('Nature', 'park'),
  culture('Culture', 'establishment'),
  nightlife('Vie nocturne', 'night_club'),
  sports('Sports', 'gym'),
  relaxation('Détente', 'spa');

  const ActivityCategory(this.displayName, this.googlePlaceType);

  final String displayName;
  final String googlePlaceType;

  static ActivityCategory? fromGoogleType(String type) {
    for (final category in ActivityCategory.values) {
      if (category.googlePlaceType == type) {
        return category;
      }
    }
    return null;
  }
}

/// Énumération des niveaux de prix
enum PriceLevel {
  free('Gratuit', 0),
  inexpensive('Bon marché', 1),
  moderate('Modéré', 2),
  expensive('Cher', 3),
  veryExpensive('Très cher', 4);

  const PriceLevel(this.displayName, this.level);

  final String displayName;
  final int level;

  static PriceLevel? fromLevel(int level) {
    for (final price in PriceLevel.values) {
      if (price.level == level) {
        return price;
      }
    }
    return null;
  }
}
