import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:geosector_app/core/constants/app_keys.dart';
import 'package:geosector_app/core/data/models/pending_request.dart';

/// Service pour gérer les entités temporaires créées en mode offline
/// Ces entités ont des IDs temporaires (temp_xxx) en attendant la synchronisation
class TempEntityService {
  static TempEntityService? _instance;
  
  static TempEntityService get instance {
    _instance ??= TempEntityService._internal();
    return _instance!;
  }
  
  TempEntityService._internal();
  
  /// Vérifie si un ID est temporaire (créé offline)
  /// Les IDs temporaires sont des entiers négatifs
  static bool isTemporaryId(dynamic id) {
    if (id == null) return false;
    if (id is int) {
      return id < 0;
    }
    // Pour compatibilité avec d'autres types d'IDs
    return id.toString().startsWith('temp_');
  }
  
  /// Vérifie si une entité avec cet ID temporaire est en attente de création
  Future<bool> isEntityPendingCreation(dynamic tempId) async {
    try {
      if (!Hive.isBoxOpen(AppKeys.pendingRequestsBoxName)) {
        return false;
      }
      
      final box = Hive.box<PendingRequest>(AppKeys.pendingRequestsBoxName);
      
      // Convertir l'ID en string pour la comparaison
      final tempIdStr = tempId.toString();
      
      // Rechercher une requête POST avec ce tempId
      for (var request in box.values) {
        if (request.tempId == tempIdStr && 
            request.method.toUpperCase() == 'POST') {
          return true;
        }
      }
      
      return false;
    } catch (e) {
      debugPrint('Erreur lors de la vérification de l\'entité temporaire: $e');
      return false;
    }
  }
  
  /// Obtient le nombre d'entités temporaires en attente
  int getTemporaryEntitiesCount() {
    try {
      if (!Hive.isBoxOpen(AppKeys.pendingRequestsBoxName)) {
        return 0;
      }
      
      final box = Hive.box<PendingRequest>(AppKeys.pendingRequestsBoxName);
      
      // Compter les requêtes POST avec tempId (créations)
      return box.values
          .where((request) => 
              request.tempId != null && 
              request.method.toUpperCase() == 'POST')
          .length;
    } catch (e) {
      debugPrint('Erreur lors du comptage des entités temporaires: $e');
      return 0;
    }
  }
  
  /// Vérifie si une modification est autorisée pour cette entité
  Future<bool> canModifyEntity(dynamic entityId) async {
    // Si ce n'est pas un ID temporaire, la modification est autorisée
    if (!isTemporaryId(entityId)) {
      return true;
    }
    
    // Si c'est un ID temporaire, vérifier s'il est en attente
    final isPending = await isEntityPendingCreation(entityId);
    
    // On peut modifier seulement si l'entité n'est PAS en attente
    return !isPending;
  }
  
  /// Affiche un message d'erreur pour une entité en attente de synchronisation
  static void showPendingSyncError(BuildContext context, {String? entityType}) {
    final entity = entityType ?? 'élément';
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Row(
          children: [
            const Icon(Icons.sync_problem, color: Colors.white),
            const SizedBox(width: 12),
            Expanded(
              child: Text(
                'Ce $entity est en attente de synchronisation.\n'
                'Reconnectez-vous à Internet pour pouvoir le modifier.',
                style: const TextStyle(color: Colors.white),
              ),
            ),
          ],
        ),
        backgroundColor: Colors.orange.shade700,
        duration: const Duration(seconds: 5),
        behavior: SnackBarBehavior.floating,
        action: SnackBarAction(
          label: 'Compris',
          textColor: Colors.white,
          onPressed: () {},
        ),
      ),
    );
  }
  
  /// Affiche une dialog explicative pour les entités en attente
  static Future<void> showPendingSyncDialog(
    BuildContext context, {
    String? entityType,
    VoidCallback? onRetry,
  }) async {
    final entity = entityType ?? 'élément';
    
    await showDialog(
      context: context,
      barrierDismissible: false,
      builder: (dialogContext) => AlertDialog(
        icon: const Icon(Icons.sync_problem, color: Colors.orange, size: 48),
        title: Text('$entity en attente'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Ce $entity a été créé hors ligne et est en attente de synchronisation avec le serveur.',
              style: const TextStyle(fontSize: 14),
            ),
            const SizedBox(height: 16),
            Container(
              padding: const EdgeInsets.all(12),
              decoration: BoxDecoration(
                color: Colors.orange.shade50,
                borderRadius: BorderRadius.circular(8),
                border: Border.all(color: Colors.orange.shade200),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Row(
                    children: [
                      Icon(Icons.info_outline, size: 16, color: Colors.orange),
                      SizedBox(width: 8),
                      Text(
                        'Que faire ?',
                        style: TextStyle(
                          fontWeight: FontWeight.bold,
                          color: Colors.orange,
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 8),
                  const Text(
                    '• Vérifiez votre connexion Internet',
                    style: TextStyle(fontSize: 13),
                  ),
                  const Text(
                    '• Attendez que la synchronisation se termine',
                    style: TextStyle(fontSize: 13),
                  ),
                  Text(
                    '• Le $entity sera modifiable après synchronisation',
                    style: const TextStyle(fontSize: 13),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 16),
            // Afficher le statut de connexion
            ValueListenableBuilder<Box<PendingRequest>>(
              valueListenable: Hive.box<PendingRequest>(AppKeys.pendingRequestsBoxName).listenable(),
              builder: (context, box, child) {
                final count = box.length;
                return Container(
                  padding: const EdgeInsets.all(8),
                  decoration: BoxDecoration(
                    color: Colors.grey.shade100,
                    borderRadius: BorderRadius.circular(6),
                  ),
                  child: Row(
                    children: [
                      const Icon(Icons.pending_actions, size: 16),
                      const SizedBox(width: 8),
                      Text(
                        '$count requête${count > 1 ? 's' : ''} en attente',
                        style: const TextStyle(fontSize: 13),
                      ),
                    ],
                  ),
                );
              },
            ),
          ],
        ),
        actions: [
          if (onRetry != null)
            TextButton(
              onPressed: () {
                Navigator.of(dialogContext).pop();
                onRetry();
              },
              child: const Text('Réessayer'),
            ),
          ElevatedButton(
            onPressed: () => Navigator.of(dialogContext).pop(),
            style: ElevatedButton.styleFrom(
              backgroundColor: Colors.orange,
            ),
            child: const Text('J\'ai compris'),
          ),
        ],
      ),
    );
  }
  
  /// Génère un ID temporaire unique (entier négatif)
  static int generateTempId() {
    // Utiliser un timestamp négatif pour garantir l'unicité
    // et éviter les conflits avec les IDs réels (positifs)
    final timestamp = DateTime.now().millisecondsSinceEpoch;
    // Ajouter un petit random pour éviter les collisions
    final random = (timestamp % 1000);
    // Retourner un nombre négatif
    return -(timestamp + random);
  }
  
  /// Génère un ID temporaire sous forme de string (pour tempId dans PendingRequest)
  static String generateTempIdString() {
    final tempId = generateTempId();
    return tempId.toString();
  }
  
  /// Extrait l'ID réel d'une réponse API après synchronisation
  /// Utilisé pour mapper les IDs temporaires aux IDs réels
  static dynamic extractRealId(Map<String, dynamic> response) {
    // L'API peut retourner l'ID dans différents champs
    return response['id'] ?? 
           response['data']?['id'] ?? 
           response['result']?['id'];
  }
}