 import 'package:cloud_firestore/cloud_firestore.dart';

/// Type d'alerte
enum AlertType {
  lowStock,            // Stock faible
  maintenanceDue,      // Maintenance à venir
  conflict,            // Conflit disponibilité
  lost,                // Équipement perdu
  eventCreated,        // Événement créé
  eventModified,       // Événement modifié
  eventCancelled,      // Événement annulé
  eventAssigned,       // Assigné à un événement
  maintenanceReminder, // Rappel maintenance périodique
  equipmentMissing,    // Équipement manquant à une étape
  quantityMismatch,    // Quantité incorrecte
  damaged,             // Équipement endommagé
  workforceAdded,      // Ajouté à la workforce d'un événement
}

/// Gravité de l'alerte
enum AlertSeverity {
  info,     // Information (bleu)
  warning,  // Avertissement (orange)
  critical, // Critique (rouge)
}

String alertTypeToString(AlertType type) {
  switch (type) {
    case AlertType.lowStock:
      return 'LOW_STOCK';
    case AlertType.maintenanceDue:
      return 'MAINTENANCE_DUE';
    case AlertType.conflict:
      return 'CONFLICT';
    case AlertType.lost:
      return 'LOST';
    case AlertType.eventCreated:
      return 'EVENT_CREATED';
    case AlertType.eventModified:
      return 'EVENT_MODIFIED';
    case AlertType.eventCancelled:
      return 'EVENT_CANCELLED';
    case AlertType.eventAssigned:
      return 'EVENT_ASSIGNED';
    case AlertType.maintenanceReminder:
      return 'MAINTENANCE_REMINDER';
    case AlertType.equipmentMissing:
      return 'EQUIPMENT_MISSING';
    case AlertType.quantityMismatch:
      return 'QUANTITY_MISMATCH';
    case AlertType.damaged:
      return 'DAMAGED';
    case AlertType.workforceAdded:
      return 'WORKFORCE_ADDED';
  }
}

AlertType alertTypeFromString(String? type) {
  switch (type) {
    case 'LOW_STOCK':
      return AlertType.lowStock;
    case 'MAINTENANCE_DUE':
      return AlertType.maintenanceDue;
    case 'CONFLICT':
      return AlertType.conflict;
    case 'LOST':
      return AlertType.lost;
    case 'EVENT_CREATED':
      return AlertType.eventCreated;
    case 'EVENT_MODIFIED':
      return AlertType.eventModified;
    case 'EVENT_CANCELLED':
      return AlertType.eventCancelled;
    case 'EVENT_ASSIGNED':
      return AlertType.eventAssigned;
    case 'MAINTENANCE_REMINDER':
      return AlertType.maintenanceReminder;
    case 'EQUIPMENT_MISSING':
      return AlertType.equipmentMissing;
    case 'QUANTITY_MISMATCH':
      return AlertType.quantityMismatch;
    case 'DAMAGED':
      return AlertType.damaged;
    case 'WORKFORCE_ADDED':
      return AlertType.workforceAdded;
    default:
      return AlertType.conflict;
  }
}

String alertSeverityToString(AlertSeverity severity) {
  switch (severity) {
    case AlertSeverity.info:
      return 'INFO';
    case AlertSeverity.warning:
      return 'WARNING';
    case AlertSeverity.critical:
      return 'CRITICAL';
  }
}

AlertSeverity alertSeverityFromString(String? severity) {
  switch (severity) {
    case 'INFO':
      return AlertSeverity.info;
    case 'WARNING':
      return AlertSeverity.warning;
    case 'CRITICAL':
      return AlertSeverity.critical;
    default:
      return AlertSeverity.info;
  }
}

class AlertModel {
  final String id;                       // ID généré automatiquement
  final AlertType type;                  // Type d'alerte
  final AlertSeverity severity;          // Gravité de l'alerte
  final String message;                  // Message de l'alerte
  final List<String> assignedToUserIds;  // Utilisateurs concernés
  final String? eventId;                 // ID de l'événement concerné (optionnel)
  final String? equipmentId;             // ID de l'équipement concerné (optionnel)
  final String? createdByUserId;         // Qui a déclenché l'alerte
  final DateTime createdAt;              // Date de création
  final DateTime? dueDate;               // Date d'échéance (pour maintenance)
  final String? actionUrl;               // URL de redirection (deep link)
  final bool isRead;                     // Statut lu/non lu
  final bool isResolved;                 // Résolue ou non
  final String? resolution;              // Message de résolution
  final DateTime? resolvedAt;            // Date de résolution
  final String? resolvedByUserId;        // Qui a résolu

  AlertModel({
    required this.id,
    required this.type,
    this.severity = AlertSeverity.info,
    required this.message,
    this.assignedToUserIds = const [],
    this.eventId,
    this.equipmentId,
    this.createdByUserId,
    required this.createdAt,
    this.dueDate,
    this.actionUrl,
    this.isRead = false,
    this.isResolved = false,
    this.resolution,
    this.resolvedAt,
    this.resolvedByUserId,
  });

  factory AlertModel.fromMap(Map<String, dynamic> map, String id) {
    // Fonction helper pour convertir Timestamp ou String ISO en DateTime
    DateTime parseDate(dynamic value) {
      if (value == null) return DateTime.now();
      if (value is Timestamp) return value.toDate();
      if (value is String) return DateTime.tryParse(value) ?? DateTime.now();
      return DateTime.now();
    }

    // Parser les assignedToUserIds (peut être List ou null)
    List<String> parseUserIds(dynamic value) {
      if (value == null) return [];
      if (value is List) return value.map((e) => e.toString()).toList();
      return [];
    }

    return AlertModel(
      id: id,
      type: alertTypeFromString(map['type']),
      severity: alertSeverityFromString(map['severity']),
      message: map['message'] ?? '',
      assignedToUserIds: parseUserIds(map['assignedToUserIds'] ?? map['assignedTo']),
      eventId: map['eventId'],
      equipmentId: map['equipmentId'],
      createdByUserId: map['createdByUserId'] ?? map['createdBy'],
      createdAt: parseDate(map['createdAt']),
      dueDate: map['dueDate'] != null ? parseDate(map['dueDate']) : null,
      actionUrl: map['actionUrl'],
      isRead: map['isRead'] ?? false,
      isResolved: map['isResolved'] ?? false,
      resolution: map['resolution'],
      resolvedAt: map['resolvedAt'] != null ? parseDate(map['resolvedAt']) : null,
      resolvedByUserId: map['resolvedByUserId'],
    );
  }

  /// Factory depuis un document Firestore
  factory AlertModel.fromFirestore(DocumentSnapshot doc) {
    final data = doc.data() as Map<String, dynamic>?;
    if (data == null) {
      throw Exception('Document vide: ${doc.id}');
    }
    return AlertModel.fromMap(data, doc.id);
  }

  Map<String, dynamic> toMap() {
    return {
      'type': alertTypeToString(type),
      'severity': alertSeverityToString(severity),
      'message': message,
      'assignedToUserIds': assignedToUserIds,
      if (eventId != null) 'eventId': eventId,
      if (equipmentId != null) 'equipmentId': equipmentId,
      if (createdByUserId != null) 'createdByUserId': createdByUserId,
      'createdAt': Timestamp.fromDate(createdAt),
      if (dueDate != null) 'dueDate': Timestamp.fromDate(dueDate!),
      if (actionUrl != null) 'actionUrl': actionUrl,
      'isRead': isRead,
      'isResolved': isResolved,
      if (resolution != null) 'resolution': resolution,
      if (resolvedAt != null) 'resolvedAt': Timestamp.fromDate(resolvedAt!),
      if (resolvedByUserId != null) 'resolvedByUserId': resolvedByUserId,
    };
  }

  AlertModel copyWith({
    String? id,
    AlertType? type,
    AlertSeverity? severity,
    String? message,
    List<String>? assignedToUserIds,
    String? eventId,
    String? equipmentId,
    String? createdByUserId,
    DateTime? createdAt,
    DateTime? dueDate,
    String? actionUrl,
    bool? isRead,
    bool? isResolved,
    String? resolution,
    DateTime? resolvedAt,
    String? resolvedByUserId,
  }) {
    return AlertModel(
      id: id ?? this.id,
      type: type ?? this.type,
      severity: severity ?? this.severity,
      message: message ?? this.message,
      assignedToUserIds: assignedToUserIds ?? this.assignedToUserIds,
      eventId: eventId ?? this.eventId,
      equipmentId: equipmentId ?? this.equipmentId,
      createdByUserId: createdByUserId ?? this.createdByUserId,
      createdAt: createdAt ?? this.createdAt,
      dueDate: dueDate ?? this.dueDate,
      actionUrl: actionUrl ?? this.actionUrl,
      isRead: isRead ?? this.isRead,
      isResolved: isResolved ?? this.isResolved,
      resolution: resolution ?? this.resolution,
      resolvedAt: resolvedAt ?? this.resolvedAt,
      resolvedByUserId: resolvedByUserId ?? this.resolvedByUserId,
    );
  }
  
  /// Helper : Retourne true si l'alerte est pour un événement
  bool get isEventAlert => 
      type == AlertType.eventCreated || 
      type == AlertType.eventModified || 
      type == AlertType.eventCancelled || 
      type == AlertType.eventAssigned;
  
  /// Helper : Retourne true si l'alerte est pour la maintenance
  bool get isMaintenanceAlert => 
      type == AlertType.maintenanceDue || 
      type == AlertType.maintenanceReminder;
  
  /// Helper : Retourne true si l'alerte est pour un équipement
  bool get isEquipmentAlert => 
      type == AlertType.lost || 
      type == AlertType.equipmentMissing || 
      type == AlertType.lowStock;
}

