import 'package:em2rp/utils/debug_log.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.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/providers/equipment_provider.dart';
import 'package:em2rp/providers/container_provider.dart';
import 'package:em2rp/utils/colors.dart';
import 'package:em2rp/views/widgets/event/equipment_selection_dialog.dart';
import 'package:em2rp/views/widgets/event_form/ai_equipment_assistant_dialog.dart';

/// Section pour afficher et gérer le matériel assigné à un événement
class EventAssignedEquipmentSection extends StatefulWidget {
  final List<EventEquipment> assignedEquipment;
  final List<String> assignedContainers; // IDs des conteneurs
  final DateTime? startDate;
  final DateTime? endDate;
  final Function(List<EventEquipment>, List<String>) onChanged;
  final String? eventId; // Pour exclure l'événement actuel de la vérification
  final String? eventTypeId;

  const EventAssignedEquipmentSection({
    super.key,
    required this.assignedEquipment,
    required this.assignedContainers,
    required this.startDate,
    required this.endDate,
    required this.onChanged,
    this.eventId,
    this.eventTypeId,
  });

  @override
  State<EventAssignedEquipmentSection> createState() =>
      _EventAssignedEquipmentSectionState();
}

class _EventAssignedEquipmentSectionState
    extends State<EventAssignedEquipmentSection> {
  bool get _canAddMaterial =>
      widget.startDate != null && widget.endDate != null;
  final Map<String, EquipmentModel> _equipmentCache = {};
  final Map<String, ContainerModel> _containerCache = {};
  bool _isLoading = true;
  final ScrollController _scrollController = ScrollController();

  @override
  void initState() {
    super.initState();
    _loadEquipmentAndContainers();
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  void didUpdateWidget(EventAssignedEquipmentSection oldWidget) {
    super.didUpdateWidget(oldWidget);
    // Recharger si les équipements ou conteneurs ont changé
    if (oldWidget.assignedEquipment != widget.assignedEquipment ||
        oldWidget.assignedContainers != widget.assignedContainers) {
      _loadEquipmentAndContainers();
    }
  }

  Future<void> _loadEquipmentAndContainers() async {
    setState(() => _isLoading = true);

    try {
      final equipmentProvider = context.read<EquipmentProvider>();
      final containerProvider = context.read<ContainerProvider>();

      DebugLog.info(
          '[EventAssignedEquipmentSection] Loading caches from assigned lists');

      // Toujours partir des données locales du formulaire pour éviter les décalages visuels.
      final equipmentIds =
          widget.assignedEquipment.map((eq) => eq.equipmentId).toList();
      final containers =
          await containerProvider.getContainersByIds(widget.assignedContainers);

      final childEquipmentIds = <String>[];
      for (final container in containers) {
        childEquipmentIds.addAll(container.equipmentIds);
      }

      final allEquipmentIds =
          <String>{...equipmentIds, ...childEquipmentIds}.toList();
      final equipment =
          await equipmentProvider.getEquipmentsByIds(allEquipmentIds);

      _equipmentCache.clear();
      _containerCache.clear();

      for (final eq in widget.assignedEquipment) {
        final equipmentItem = equipment.firstWhere(
          (e) => e.id == eq.equipmentId,
          orElse: () => EquipmentModel(
            id: eq.equipmentId,
            name: 'Équipement inconnu',
            category: EquipmentCategory.other,
            status: EquipmentStatus.available,
            maintenanceIds: [],
            createdAt: DateTime.now(),
            updatedAt: DateTime.now(),
          ),
        );
        _equipmentCache[eq.equipmentId] = equipmentItem;
      }

      for (final containerId in widget.assignedContainers) {
        final container = containers.firstWhere(
          (c) => c.id == containerId,
          orElse: () => ContainerModel(
            id: containerId,
            name: 'Conteneur inconnu',
            type: ContainerType.flightCase,
            status: EquipmentStatus.available,
            equipmentIds: [],
            updatedAt: DateTime.now(),
            createdAt: DateTime.now(),
          ),
        );
        _containerCache[containerId] = container;
      }
    } catch (e) {
      DebugLog.error(
          '[EventAssignedEquipmentSection] Error loading equipment and containers',
          e);
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _openSelectionDialog() async {
    if (widget.startDate == null || widget.endDate == null) {
      return; // Ne devrait jamais arriver car le bouton est désactivé
    }

    final result = await showDialog<Map<String, SelectedItem>>(
      context: context,
      builder: (context) => EquipmentSelectionDialog(
        startDate: widget.startDate!,
        endDate: widget.endDate!,
        alreadyAssigned: widget.assignedEquipment,
        alreadyAssignedContainers: widget.assignedContainers,
        excludeEventId: widget.eventId,
      ),
    );

    if (result != null && result.isNotEmpty) {
      await _processSelection(result);
    }
  }

  Future<void> _processSelection(Map<String, SelectedItem> selection) async {
    DebugLog.info(
        '[EventAssignedEquipmentSection] Processing selection of ${selection.length} items');

    // Séparer équipements et conteneurs
    final newEquipment = <EventEquipment>[];
    final newContainers = <String>[];

    for (var item in selection.values) {
      if (item.type == SelectionType.equipment) {
        newEquipment.add(EventEquipment(
          equipmentId: item.id,
          quantity: item.quantity,
        ));
      } else {
        newContainers.add(item.id);
      }
    }

    DebugLog.info(
        '[EventAssignedEquipmentSection] Found ${newEquipment.length} equipment(s) and ${newContainers.length} container(s)');

    // 🔧 FIX: Pour chaque container sélectionné, ajouter aussi ses équipements enfants
    if (newContainers.isNotEmpty) {
      final containerProvider = context.read<ContainerProvider>();
      final containers =
          await containerProvider.getContainersByIds(newContainers);

      for (var container in containers) {
        for (var childEquipmentId in container.equipmentIds) {
          // Vérifier si l'équipement enfant n'est pas déjà dans la liste
          final existsInNew =
              newEquipment.any((eq) => eq.equipmentId == childEquipmentId);
          if (!existsInNew) {
            newEquipment.add(EventEquipment(
              equipmentId: childEquipmentId,
              quantity: 1,
            ));
            DebugLog.info(
                '[EventAssignedEquipmentSection] Adding child equipment $childEquipmentId from container ${container.id}');
          }
        }
      }
    }

    // ✅ Pas de vérification de conflits : déjà fait dans le pop-up
    // On enregistre directement la sélection

    // Fusionner avec l'existant
    final updatedEquipment = [...widget.assignedEquipment];
    final updatedContainers = [...widget.assignedContainers];

    // Pour chaque nouvel équipement
    for (var eq in newEquipment) {
      final existingIndex =
          updatedEquipment.indexWhere((e) => e.equipmentId == eq.equipmentId);

      if (existingIndex != -1) {
        // L'équipement existe déjà : mettre à jour la quantité
        updatedEquipment[existingIndex] = EventEquipment(
          equipmentId: eq.equipmentId,
          quantity: eq.quantity, // Utiliser la nouvelle quantité
          isPrepared: updatedEquipment[existingIndex].isPrepared,
          isLoaded: updatedEquipment[existingIndex].isLoaded,
          isUnloaded: updatedEquipment[existingIndex].isUnloaded,
          isReturned: updatedEquipment[existingIndex].isReturned,
          quantityAtReturn: updatedEquipment[existingIndex].quantityAtReturn,
        );
      } else {
        // L'équipement n'existe pas : l'ajouter
        updatedEquipment.add(eq);
      }
    }

    for (var containerId in newContainers) {
      if (!updatedContainers.contains(containerId)) {
        updatedContainers.add(containerId);
      }
    }

    // Notifier le changement
    widget.onChanged(updatedEquipment, updatedContainers);
  }

  Future<void> _openAiAssistantDialog() async {
    if (widget.startDate == null || widget.endDate == null) {
      return;
    }

    final result = await showDialog<AiProposalResult>(
      context: context,
      builder: (context) => AiEquipmentAssistantDialog(
        startDate: widget.startDate!,
        endDate: widget.endDate!,
        eventTypeId: widget.eventTypeId,
        excludeEventId: widget.eventId,
        currentAssignedEquipment: widget.assignedEquipment,
      ),
    );

    if (result == null) {
      return;
    }

    _applyAiProposal(result);
  }

  void _applyAiProposal(AiProposalResult result) async {
    final existingById = {
      for (final equipment in widget.assignedEquipment)
        equipment.equipmentId: equipment,
    };

    final updatedEquipment = result.equipment.map((proposed) {
      final existing = existingById[proposed.equipmentId];
      if (existing == null) {
        return proposed;
      }
      return existing.copyWith(quantity: proposed.quantity, rationale: proposed.rationale);
    }).toList();

    // 🔧 FIX: Pour chaque container ajouté par l'IA, ajouter aussi ses équipements enfants
    if (result.containerIds.isNotEmpty) {
      final containerProvider = context.read<ContainerProvider>();
      final containers = await containerProvider.getContainersByIds(result.containerIds);

      for (var container in containers) {
        for (var childEquipmentId in container.equipmentIds) {
          // Vérifier si l'équipement enfant n'est pas déjà dans la liste (ou déjà ajouté par la proposition)
          final exists = updatedEquipment.any((eq) => eq.equipmentId == childEquipmentId);
          if (!exists) {
            updatedEquipment.add(EventEquipment(
              equipmentId: childEquipmentId,
              quantity: 1,
              rationale: 'Inclus dans ${container.id}',
            ));
            DebugLog.info('[EventAssignedEquipmentSection] AI adding child equipment $childEquipmentId from container ${container.id}');
          }
        }
      }
    }

    final updatedContainers = [...widget.assignedContainers];
    for (final containerId in result.containerIds) {
      if (!updatedContainers.contains(containerId)) {
        updatedContainers.add(containerId);
      }
    }

    widget.onChanged(updatedEquipment, updatedContainers);
  }

  void _removeEquipment(String equipmentId) {
    final updated = widget.assignedEquipment
        .where((eq) => eq.equipmentId != equipmentId)
        .toList();

    widget.onChanged(updated, widget.assignedContainers);
    setState(() {
      _equipmentCache.remove(equipmentId);
    });
  }

  void _removeContainer(String containerId) {
    // Récupérer le conteneur pour obtenir la liste de ses enfants
    final container = _containerCache[containerId];

    // Retirer le conteneur de la liste
    final updatedContainers =
        widget.assignedContainers.where((id) => id != containerId).toList();

    // 🔧 FIX: Ne supprimer les équipements enfants QUE s'ils ne sont pas dans un autre container
    final updatedEquipment = <EventEquipment>[];

    if (container != null) {
      // Collecter les IDs d'équipements dans les autres containers
      final Set<String> equipmentIdsInOtherContainers = {};
      for (var otherContainerId in updatedContainers) {
        final otherContainer = _containerCache[otherContainerId];
        if (otherContainer != null) {
          equipmentIdsInOtherContainers.addAll(otherContainer.equipmentIds);
        }
      }

      // Garder les équipements qui :
      // 1. Ne sont PAS dans le container supprimé OU
      // 2. Sont dans le container supprimé MAIS aussi dans un autre container
      for (var eq in widget.assignedEquipment) {
        final isInRemovedContainer =
            container.equipmentIds.contains(eq.equipmentId);
        final isInOtherContainer =
            equipmentIdsInOtherContainers.contains(eq.equipmentId);

        if (!isInRemovedContainer || isInOtherContainer) {
          updatedEquipment.add(eq);
        }
      }
    } else {
      // Si le container n'est pas dans le cache, garder tous les équipements
      updatedEquipment.addAll(widget.assignedEquipment);
    }

    // Notifier le changement avec les deux listes mises à jour
    widget.onChanged(updatedEquipment, updatedContainers);

    setState(() {
      _containerCache.remove(containerId);
      // Nettoyer le cache uniquement pour les équipements effectivement supprimés
      if (container != null) {
        final remainingEquipmentIds =
            updatedEquipment.map((eq) => eq.equipmentId).toSet();
        for (var equipmentId in container.equipmentIds) {
          if (!remainingEquipmentIds.contains(equipmentId)) {
            _equipmentCache.remove(equipmentId);
          }
        }
      }
    });
  }

  /// Récupère les équipements qui ne sont PAS dans un conteneur assigné
  List<EventEquipment> _getStandaloneEquipment() {
    // Collecter tous les IDs des équipements qui sont dans des conteneurs assignés
    final Set<String> equipmentIdsInContainers = {};

    for (var containerId in widget.assignedContainers) {
      final container = _containerCache[containerId];
      if (container != null) {
        equipmentIdsInContainers.addAll(container.equipmentIds);
      }
    }

    // Filtrer les équipements assignés pour garder uniquement ceux qui ne sont pas dans un conteneur
    return widget.assignedEquipment
        .where((eq) => !equipmentIdsInContainers.contains(eq.equipmentId))
        .toList();
  }

  @override
  Widget build(BuildContext context) {
    final totalItems =
        widget.assignedEquipment.length + widget.assignedContainers.length;

    return Card(
      elevation: 0,
      color: Colors.white,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(16),
        side: BorderSide(color: Colors.grey.shade200, width: 1),
      ),
      child: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // En-tête
            SizedBox(
              width: double.infinity,
              child: Wrap(
                spacing: 16,
                runSpacing: 16,
                crossAxisAlignment: WrapCrossAlignment.center,
                alignment: WrapAlignment.spaceBetween,
                children: [
                  Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Container(
                        padding: const EdgeInsets.all(10),
                        decoration: BoxDecoration(
                          color: AppColors.rouge.withOpacity(0.1),
                          borderRadius: BorderRadius.circular(10),
                        ),
                        child: const Icon(
                          Icons.inventory_2,
                          color: AppColors.rouge,
                          size: 22,
                        ),
                      ),
                      const SizedBox(width: 16),
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          const Text(
                            'Matériel assigné',
                            style: TextStyle(
                              fontSize: 18,
                              fontWeight: FontWeight.bold,
                              color: Colors.black87,
                            ),
                          ),
                          Text(
                            '$totalItems élément(s)',
                            style: TextStyle(
                              fontSize: 14,
                              color: Colors.grey.shade600,
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                  Wrap(
                    spacing: 8,
                    runSpacing: 8,
                    children: [
                      ActionChip(
                        onPressed: _canAddMaterial ? _openAiAssistantDialog : null,
                        avatar: const Icon(Icons.auto_fix_high, size: 18),
                        label: const Text('Assistant IA'),
                      ),
                      ElevatedButton.icon(
                        onPressed: _canAddMaterial ? _openSelectionDialog : null,
                        icon: Icon(Icons.add,
                            color: _canAddMaterial ? Colors.white : Colors.grey),
                        label: Text(
                          'Ajouter',
                          style: TextStyle(
                              color: _canAddMaterial ? Colors.white : Colors.grey),
                        ),
                        style: ElevatedButton.styleFrom(
                          backgroundColor: _canAddMaterial
                              ? AppColors.rouge
                              : Colors.grey.shade300,
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),

            // Message si dates non sélectionnées
            if (!_canAddMaterial)
              Padding(
                padding: const EdgeInsets.only(top: 8),
                child: Text(
                  'Veuillez sélectionner les dates de début et de fin pour ajouter du matériel',
                  style: TextStyle(
                    fontSize: 12,
                    color: Colors.orange.shade700,
                    fontStyle: FontStyle.italic,
                  ),
                ),
              ),

            const SizedBox(height: 16),
            const Divider(),
            const SizedBox(height: 16),

            // Contenu
            if (_isLoading)
              const Center(
                child: Padding(
                  padding: EdgeInsets.all(32),
                  child: CircularProgressIndicator(),
                ),
              )
            else if (totalItems == 0)
              Center(
                child: Padding(
                  padding: const EdgeInsets.all(32),
                  child: Column(
                    children: [
                      Icon(
                        Icons.inventory_2_outlined,
                        size: 64,
                        color: Colors.grey.shade400,
                      ),
                      const SizedBox(height: 16),
                      Text(
                        'Aucun matériel assigné',
                        style: TextStyle(
                          fontSize: 16,
                          color: Colors.grey.shade600,
                        ),
                      ),
                      const SizedBox(height: 8),
                      Text(
                        'Cliquez sur "Ajouter" pour sélectionner du matériel',
                        style: TextStyle(
                          fontSize: 14,
                          color: Colors.grey.shade500,
                        ),
                      ),
                    ],
                  ),
                ),
              )
            else
              Container(
                constraints: const BoxConstraints(maxHeight: 400),
                decoration: BoxDecoration(
                  border: Border.all(color: Colors.grey.shade200),
                  borderRadius: BorderRadius.circular(8),
                  color: Colors.grey.shade50,
                ),
                child: SingleChildScrollView(
                  controller: _scrollController,
                  padding: const EdgeInsets.all(12),
                  child: LayoutBuilder(
                    builder: (context, constraints) {
                      final hasContainers = widget.assignedContainers.isNotEmpty;
                      final hasEquipment = _getStandaloneEquipment().isNotEmpty;

                      final containersContent = Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          if (hasContainers) ...[
                            Text(
                              'Boîtes (${widget.assignedContainers.length})',
                              style: const TextStyle(
                                fontWeight: FontWeight.bold,
                                fontSize: 16,
                              ),
                            ),
                            const SizedBox(height: 8),
                            ...widget.assignedContainers.map((containerId) {
                              final container = _containerCache[containerId];
                              return _buildContainerItem(container);
                            }),
                            const SizedBox(height: 16),
                          ]
                        ],
                      );

                      final equipmentContent = Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          if (hasEquipment) ...[
                            Text(
                              'Équipements (${_getStandaloneEquipment().length})',
                              style: const TextStyle(
                                fontWeight: FontWeight.bold,
                                fontSize: 16,
                              ),
                            ),
                            const SizedBox(height: 8),
                            ..._getStandaloneEquipment().map((eq) {
                              final equipment = _equipmentCache[eq.equipmentId];
                              return _buildEquipmentItem(equipment, eq);
                            }),
                          ]
                        ],
                      );

                      if (constraints.maxWidth > 600 && hasContainers && hasEquipment) {
                        return Row(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Expanded(child: containersContent),
                            const SizedBox(width: 24),
                            Expanded(child: equipmentContent),
                          ],
                        );
                      } else {
                        return Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            containersContent,
                            equipmentContent,
                          ],
                        );
                      }
                    },
                  ),
                ),
              ),
          ],
        ),
      ),
    );
  }

  Widget _buildContainerItem(ContainerModel? container) {
    if (container == null) {
      return const Card(
        margin: EdgeInsets.only(bottom: 8),
        child: ListTile(
          leading: Icon(Icons.inventory_2, color: Colors.grey),
          title: Text('Conteneur inconnu'),
          subtitle: Text('Données du conteneur indisponibles'),
        ),
      );
    }

    return Card(
      margin: const EdgeInsets.only(bottom: 8),
      child: ExpansionTile(
        leading: container.type.getIcon(size: 24, color: AppColors.rouge),
        title: Text(
          container.id,
          style: const TextStyle(fontWeight: FontWeight.bold),
        ),
        subtitle: Text(container.name),
        trailing: IconButton(
          icon: const Icon(Icons.delete, color: Colors.red),
          onPressed: () => _removeContainer(container.id),
        ),
        children: [
          // 🔧 FIX: Utiliser directement le cache local au lieu du provider stream
          Builder(
            builder: (context) {
              // Récupérer les équipements enfants depuis le cache local
              final childEquipments = container.equipmentIds
                  .map((id) => _equipmentCache[id])
                  .where((eq) => eq != null)
                  .cast<EquipmentModel>()
                  .toList();

              if (childEquipments.isEmpty) {
                return Padding(
                  padding: const EdgeInsets.all(16),
                  child: Text(
                    'Aucun équipement dans ce conteneur (${container.equipmentIds.length} attendu(s))',
                    style: const TextStyle(color: Colors.grey, fontSize: 12),
                  ),
                );
              }

              return Padding(
                padding:
                    const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Contenu (${childEquipments.length} équipement(s))',
                      style: TextStyle(
                        fontSize: 12,
                        color: Colors.grey.shade700,
                        fontWeight: FontWeight.w500,
                      ),
                    ),
                    const SizedBox(height: 8),
                    ...childEquipments.map((eq) {
                      return Padding(
                        padding: const EdgeInsets.only(bottom: 4),
                        child: Row(
                          children: [
                            const SizedBox(width: 16),
                            Icon(
                              Icons.subdirectory_arrow_right,
                              size: 16,
                              color: Colors.grey.shade600,
                            ),
                            const SizedBox(width: 8),
                            eq.category
                                .getIcon(size: 16, color: eq.category.color),
                            const SizedBox(width: 8),
                            Expanded(
                              child: Text(
                                eq.id,
                                style: TextStyle(
                                  fontSize: 13,
                                  color: Colors.grey.shade700,
                                ),
                              ),
                            ),
                          ],
                        ),
                      );
                    }),
                  ],
                ),
              );
            },
          ),
        ],
      ),
    );
  }

  Widget _buildEquipmentItem(
      EquipmentModel? equipment, EventEquipment eventEq) {
    if (equipment == null) {
      return Card(
        margin: const EdgeInsets.only(bottom: 8),
        child: ListTile(
          leading: const CircleAvatar(
            backgroundColor: Color(0xFFE0E0E0),
            child: Icon(Icons.inventory_2, color: Colors.grey),
          ),
          title: Text(
            eventEq.equipmentId,
            style: const TextStyle(fontWeight: FontWeight.bold),
          ),
          subtitle: const Text('Équipement indisponible dans le cache local'),
          trailing: IconButton(
            icon: const Icon(Icons.delete, color: Colors.red),
            onPressed: () => _removeEquipment(eventEq.equipmentId),
          ),
        ),
      );
    }

    final isConsumable = equipment.category == EquipmentCategory.consumable ||
        equipment.category == EquipmentCategory.cable;

    return Card(
      margin: const EdgeInsets.only(bottom: 8),
      child: ListTile(
        leading: CircleAvatar(
          backgroundColor: equipment.category.color.withValues(alpha: 0.2),
          child: equipment.category
              .getIconForAvatar(size: 24, color: equipment.category.color),
        ),
        title: Text(
          equipment.id,
          style: const TextStyle(fontWeight: FontWeight.bold),
        ),
        subtitle: equipment.brand != null || equipment.model != null
            ? Text('${equipment.brand ?? ''} ${equipment.model ?? ''}'.trim())
            : null,
        trailing: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            if (isConsumable)
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                decoration: BoxDecoration(
                  color: Colors.blue.shade100,
                  borderRadius: BorderRadius.circular(12),
                ),
                child: Text(
                  'Qté: ${eventEq.quantity}',
                  style: TextStyle(
                    color: Colors.blue.shade900,
                    fontWeight: FontWeight.bold,
                    fontSize: 12,
                  ),
                ),
              ),
            const SizedBox(width: 8),
            IconButton(
              icon: const Icon(Icons.delete, color: Colors.red),
              onPressed: () => _removeEquipment(equipment.id),
            ),
          ],
        ),
      ),
    );
  }
}
