import 'package:flutter/foundation.dart';
import 'package:em2rp/models/event_model.dart';
import 'package:em2rp/models/equipment_model.dart';
import 'package:em2rp/models/container_model.dart';
import 'package:em2rp/services/api_service.dart';
import 'package:em2rp/services/data_service.dart';

/// Type de conflit
enum ConflictType {
  equipmentUnavailable,   // Équipement non quantifiable utilisé
  insufficientQuantity,   // Quantité insuffisante pour consommable/câble
  containerFullyUsed,     // Boîte complète utilisée
  containerPartiallyUsed, // Certains équipements de la boîte utilisés
}

/// Informations sur un conflit de disponibilité
class AvailabilityConflict {
  final String equipmentId;
  final String equipmentName;
  final EventModel conflictingEvent;
  final int overlapDays;
  final ConflictType type;

  // Pour les quantités (consommables/câbles)
  final int? totalQuantity;
  final int? availableQuantity;
  final int? requestedQuantity;
  final int? reservedQuantity;

  // Pour les boîtes
  final String? containerId;
  final String? containerName;
  final List<String>? conflictingChildrenIds;

  AvailabilityConflict({
    required this.equipmentId,
    required this.equipmentName,
    required this.conflictingEvent,
    required this.overlapDays,
    this.type = ConflictType.equipmentUnavailable,
    this.totalQuantity,
    this.availableQuantity,
    this.requestedQuantity,
    this.reservedQuantity,
    this.containerId,
    this.containerName,
    this.conflictingChildrenIds,
  });

  /// Message descriptif du conflit
  String get conflictMessage {
    switch (type) {
      case ConflictType.equipmentUnavailable:
        return 'Équipement déjà utilisé';
      case ConflictType.insufficientQuantity:
        return 'Stock insuffisant : $availableQuantity/$totalQuantity disponible (demandé: $requestedQuantity)';
      case ConflictType.containerFullyUsed:
        return 'Boîte complète déjà utilisée';
      case ConflictType.containerPartiallyUsed:
        final count = conflictingChildrenIds?.length ?? 0;
        return '$count équipement(s) de la boîte déjà utilisé(s)';
    }
  }
}

/// Service pour vérifier la disponibilité du matériel
class EventAvailabilityService {
  final DataService _dataService = DataService(apiService);

  /// Vérifie si un équipement est disponible pour une plage de dates via Cloud Function
  Future<List<AvailabilityConflict>> checkEquipmentAvailability({
    required String equipmentId,
    required String equipmentName,
    required DateTime startDate,
    required DateTime endDate,
    String? excludeEventId,
  }) async {
    final conflicts = <AvailabilityConflict>[];

    try {
      if (kDebugMode) debugPrint('[EventAvailabilityService] Checking availability for equipment $equipmentId ($equipmentName)');

      final result = await _dataService.checkEquipmentAvailability(
        equipmentId: equipmentId,
        startDate: startDate,
        endDate: endDate,
        excludeEventId: excludeEventId,
      );

      final available = result['available'] as bool? ?? true;
      if (!available) {
        final conflictsData = result['conflicts'] as List<dynamic>? ?? [];
        for (final conflictData in conflictsData) {
          final conflict = conflictData as Map<String, dynamic>;
          final eventId = conflict['eventId'] as String;
          final eventData = conflict['eventData'] as Map<String, dynamic>?;

          if (eventData != null && eventData.isNotEmpty) {
            try {
              final event = EventModel.fromMap(eventData, eventId);
              conflicts.add(AvailabilityConflict(
                equipmentId: equipmentId,
                equipmentName: equipmentName,
                conflictingEvent: event,
                overlapDays: conflict['overlapDays'] as int? ?? 0,
              ));
            } catch (e) {
              if (kDebugMode) debugPrint('[EventAvailabilityService] Error creating EventModel: $e');
            }
          }
        }
      }
    } catch (e) {
      if (kDebugMode) debugPrint('[EventAvailabilityService] Error checking availability: $e');
    }

    return conflicts;
  }

  /// Vérifie la disponibilité pour une liste d'équipements
  Future<Map<String, List<AvailabilityConflict>>> checkMultipleEquipmentAvailability({
    required List<String> equipmentIds,
    required Map<String, String> equipmentNames,
    required DateTime startDate,
    required DateTime endDate,
    String? excludeEventId,
  }) async {
    final allConflicts = <String, List<AvailabilityConflict>>{};

    for (var equipmentId in equipmentIds) {
      final conflicts = await checkEquipmentAvailability(
        equipmentId: equipmentId,
        equipmentName: equipmentNames[equipmentId] ?? equipmentId,
        startDate: startDate,
        endDate: endDate,
        excludeEventId: excludeEventId,
      );

      if (conflicts.isNotEmpty) {
        allConflicts[equipmentId] = conflicts;
      }
    }

    return allConflicts;
  }

  /// Vérifie la disponibilité d'une boîte et de son contenu via le backend
  Future<List<AvailabilityConflict>> checkContainerAvailability({
    required ContainerModel container,
    required List<EquipmentModel> containerEquipment,
    required DateTime startDate,
    required DateTime endDate,
    String? excludeEventId,
  }) async {
    final conflicts = <AvailabilityConflict>[];

    try {
      final result = await _dataService.checkContainerAvailability(
        containerId: container.id,
        startDate: startDate,
        endDate: endDate,
        excludeEventId: excludeEventId,
      );

      final isAvailable = result['isAvailable'] as bool? ?? true;
      if (!isAvailable) {
        final conflictType = result['conflictType'] as String?;
        
        if (conflictType == 'complete') {
          final containerConflicts = result['containerConflicts'] as List<dynamic>? ?? [];
          for (var conflictData in containerConflicts) {
            final conflict = conflictData as Map<String, dynamic>;
            final eventId = conflict['eventId'] as String;
            final eventName = conflict['eventName'] as String? ?? '';
            final startDateStr = conflict['startDate'] as String?;
            final endDateStr = conflict['endDate'] as String?;
            
            final event = EventModel(
              id: eventId,
              name: eventName,
              description: '',
              startDateTime: startDateStr != null ? DateTime.tryParse(startDateStr) ?? DateTime.now() : DateTime.now(),
              endDateTime: endDateStr != null ? DateTime.tryParse(endDateStr) ?? DateTime.now() : DateTime.now(),
              basePrice: 0.0,
              installationTime: 0,
              disassemblyTime: 0,
              eventTypeId: '',
              customerId: '',
              address: '',
              latitude: 0.0,
              longitude: 0.0,
              workforce: const [],
              documents: const [],
            );
            
            conflicts.add(AvailabilityConflict(
              equipmentId: container.id,
              equipmentName: container.name,
              conflictingEvent: event,
              overlapDays: conflict['overlapDays'] as int? ?? 0,
              type: ConflictType.containerFullyUsed,
              containerId: container.id,
              containerName: container.name,
            ));
          }
        }
      }
    } catch (e) {
      if (kDebugMode) debugPrint('[EventAvailabilityService] Error checking container availability: $e');
    }

    return conflicts;
  }
}
