import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:itrimobe/services/restaurant_api_service.dart';
import 'package:itrimobe/models/printerModel.dart';
import 'dart:io';
import 'dart:convert';
import '../pages/commandes_screen.dart';

// Énumération pour les différents états de connexion
enum PrinterConnectionStatus {
  notConfigured,
  connecting,
  connected,
  disconnected,
  error
}

// Classe pour les résultats de test de connexion
class ConnectionTestResult {
  final bool isSuccessful;
  final String message;
  final PrinterConnectionStatus status;
  final Duration responseTime;

  const ConnectionTestResult({
    required this.isSuccessful,
    required this.message,
    required this.status,
    required this.responseTime,
  });

  @override
  String toString() => 'ConnectionTestResult(success: $isSuccessful, message: "$message", time: ${responseTime.inMilliseconds}ms)';
}

class OrderPrinter {
  // Singleton pattern pour garantir une seule instance
  static OrderPrinter? _instance;
  static OrderPrinter get instance => _instance ??= OrderPrinter._internal();
  OrderPrinter._internal();

  // Configuration de l'imprimante
  PrinterSettings? _settings;
  PrinterConnectionStatus _connectionStatus = PrinterConnectionStatus.notConfigured;

  DateTime? _lastConfigUpdate;
  static const Duration _configCacheTimeout = Duration(minutes: 5);

  // Getters publics
  PrinterSettings? get settings => _settings;
  PrinterConnectionStatus get connectionStatus => _connectionStatus;
  
  // Getter isConfigured modifié pour inclure validation temporelle
  bool get isConfigured {
    // Vérifier si la configuration existe
    if (_settings == null || 
        _settings!.ipAddress == null || 
        _settings!.ipAddress!.isEmpty ||
        _settings!.port == null) {
      return false;
    }
    
    // Vérifier si la configuration n'est pas trop ancienne
    if (_lastConfigUpdate != null && 
        DateTime.now().difference(_lastConfigUpdate!) > _configCacheTimeout) {
      if (kDebugMode) {
        print("⚠️ Configuration expirée, rechargement nécessaire");
      }
      return false;
    }
    
    return true;
  }

  // Constantes ESC/POS
  static const List<int> ESC_CONDENSED_ON = [0x1B, 0x0F];
  static const List<int> ESC_CONDENSED_OFF = [0x1B, 0x12];
  static const List<int> ESC_INIT = [0x1B, 0x40];
  static const List<int> ESC_ALIGN_CENTER = [0x1B, 0x61, 0x01];
  static const List<int> ESC_ALIGN_LEFT = [0x1B, 0x61, 0x00];
  static const List<int> ESC_ALIGN_RIGHT = [0x1B, 0x61, 0x02];
  static const List<int> ESC_DOUBLE_SIZE = [0x1D, 0x21, 0x11];
  static const List<int> ESC_NORMAL_SIZE = [0x1D, 0x23, 0x00];
  static const List<int> ESC_BOLD_ON = [0x1B, 0x45, 0x01];
  static const List<int> ESC_BOLD_OFF = [0x1B, 0x45, 0x00];
  static const List<int> ESC_CUT = [0x1D, 0x56, 0x00];
  static const List<int> ESC_PAGE_WIDTH_80MM = [0x1D, 0x57, 0x00, 0x02];
  static const List<int> ESC_LEFT_MARGIN_0 = [0x1D, 0x4C, 0x015, 0x00];

  // Configuration d'impression
  static const int maxCharsPerLine = 42;
  static const String checkbox = '[ ]';
  static const String rightWord = 'cocher';
  static const int padding = 1;

  /// Force la réinitialisation complète de l'instance
  static void resetInstance() {
    if (kDebugMode) {
      print("🔄 Réinitialisation complète de l'instance OrderPrinter");
    }
    _instance = null;
  }

  /// Méthode pour vider complètement le cache et recharger
  Future<bool> forceClearAndReload() async {
    if (kDebugMode) {
      print("🧹 Nettoyage complet de la configuration...");
    }
    
    // Effacer complètement tout
    _settings = null;
    _lastConfigUpdate = null;
    _connectionStatus = PrinterConnectionStatus.notConfigured;
    
    if (kDebugMode) {
      print("🔄 Rechargement forcé depuis l'API...");
    }
    
    // Attendre un peu pour s'assurer que tout est nettoyé
    await Future.delayed(const Duration(milliseconds: 100));
    
    // Recharger depuis l'API avec un timeout plus court pour déboguer
    try {
      var printerSettings = await RestaurantApiService.getPrinterSettings()
          .timeout(
            const Duration(seconds: 8),
            onTimeout: () => throw TimeoutException('Timeout lors de la récupération'),
          );

      if (kDebugMode) {
        print("📡 Nouvelle config reçue de l'API:");
        print("   IP: ${printerSettings.ipAddress}");
        print("   Port: ${printerSettings.port}");
      }

      // Validation
      if (printerSettings.ipAddress == null || printerSettings.ipAddress!.isEmpty) {
        throw ArgumentError('Adresse IP non définie');
      }

      if (printerSettings.port == null || printerSettings.port! <= 0) {
        throw ArgumentError('Port invalide');
      }

      if (!_isValidIpAddress(printerSettings.ipAddress!)) {
        throw ArgumentError('Format IP invalide: ${printerSettings.ipAddress}');
      }

      // Appliquer la nouvelle configuration
      _settings = printerSettings;
      _lastConfigUpdate = DateTime.now();
      _connectionStatus = PrinterConnectionStatus.disconnected;

      if (kDebugMode) {
        print("✅ Configuration mise à jour avec succès:");
        print("   Nouvelle IP: ${_settings!.ipAddress}");
        print("   Nouveau Port: ${_settings!.port}");
      }

      return true;

    } catch (e) {
      if (kDebugMode) {
        print("❌ Erreur lors du rechargement forcé: $e");
      }
      _connectionStatus = PrinterConnectionStatus.error;
      return false;
    }
  }

  /// Méthode de débogage pour vérifier l'état actuel
  void debugCurrentState() {
    if (kDebugMode) {
      print("🔍 État actuel de OrderPrinter:");
      print("   isConfigured: $isConfigured");
      print("   connectionStatus: $_connectionStatus");
      print("   settings: ${_settings != null ? '${_settings!.ipAddress}:${_settings!.port}' : 'null'}");
      print("   lastConfigUpdate: $_lastConfigUpdate");
      if (_lastConfigUpdate != null) {
        final age = DateTime.now().difference(_lastConfigUpdate!);
        print("   config age: ${age.inMinutes} minutes");
      }
    }
  }

  /// Initialise la configuration de l'imprimante avec gestion d'erreurs robuste
  Future<bool> initialize() async {
    try {
      _connectionStatus = PrinterConnectionStatus.connecting;
      
      if (kDebugMode) {
        print("🔧 Initialisation de la configuration imprimante...");
        print("   État avant: ${_settings != null ? '${_settings!.ipAddress}:${_settings!.port}' : 'null'}");
      }

      // Forcer la récupération depuis l'API
      var printerSettings = await RestaurantApiService.getPrinterSettings()
          .timeout(
            const Duration(seconds: 10),
            onTimeout: () => throw TimeoutException('Timeout lors de la récupération des paramètres'),
          );

      if (kDebugMode) {
        print("📡 Réponse de l'API:");
        print("   IP reçue: ${printerSettings.ipAddress}");
        print("   Port reçu: ${printerSettings.port}");
        print("   Nom: ${printerSettings.name}");
      }

      // Validation des paramètres
      if (printerSettings.ipAddress == null || printerSettings.ipAddress!.isEmpty) {
        throw ArgumentError('Adresse IP de l\'imprimante non définie');
      }

      if (printerSettings.port == null || printerSettings.port! <= 0 || printerSettings.port! > 65535) {
        throw ArgumentError('Port de l\'imprimante invalide: ${printerSettings.port}');
      }

      // Validation du format IP
      if (!_isValidIpAddress(printerSettings.ipAddress!)) {
        throw ArgumentError('Format d\'adresse IP invalide: ${printerSettings.ipAddress}');
      }

      // Vérifier si la configuration a changé
      bool configChanged = _settings == null || 
          _settings!.ipAddress != printerSettings.ipAddress ||
          _settings!.port != printerSettings.port;

      if (configChanged) {
        if (kDebugMode) {
          print("🔄 Changement de configuration détecté:");
          if (_settings != null) {
            print("   Ancienne: ${_settings!.ipAddress}:${_settings!.port}");
          } else {
            print("   Ancienne: null");
          }
          print("   Nouvelle: ${printerSettings.ipAddress}:${printerSettings.port}");
        }
        // Réinitialiser le statut de connexion
        _connectionStatus = PrinterConnectionStatus.disconnected;
      } else {
        if (kDebugMode) {
          print("ℹ️ Aucun changement de configuration");
        }
      }

      // Configuration réussie
      _settings = printerSettings;
      _lastConfigUpdate = DateTime.now();

      if (kDebugMode) {
        print("✅ Configuration appliquée:");
        print("   IP finale: ${_settings!.ipAddress}");
        print("   Port final: ${_settings!.port}");
        print("   Statut: $_connectionStatus");
      }

      return true;

    } on TimeoutException catch (e) {
      _connectionStatus = PrinterConnectionStatus.error;
      _settings = null;
      _lastConfigUpdate = null;
      if (kDebugMode) {
        print("⏰ Timeout lors de l'initialisation: $e");
      }
      return false;
    } on ArgumentError catch (e) {
      _connectionStatus = PrinterConnectionStatus.error;
      _settings = null;
      _lastConfigUpdate = null;
      if (kDebugMode) {
        print("❌ Paramètres invalides: $e");
      }
      return false;
    } catch (e) {
      _connectionStatus = PrinterConnectionStatus.error;
      _settings = null;
      _lastConfigUpdate = null;
      if (kDebugMode) {
        print("💥 Erreur lors de la récupération des paramètres d'imprimante : $e");
      }
      return false;
    }
  }

  /// Nouvelle méthode pour forcer la revalidation
  Future<bool> forceReload() async {
    if (kDebugMode) {
      print("🔄 Rechargement forcé de la configuration imprimante");
    }
    
    // Effacer la configuration actuelle
    _settings = null;
    _lastConfigUpdate = null;
    _connectionStatus = PrinterConnectionStatus.notConfigured;
    
    // Recharger depuis l'API
    return await initialize();
  }

  /// Valide le format d'une adresse IP
  bool _isValidIpAddress(String ip) {
    final ipRegex = RegExp(r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$');
    return ipRegex.hasMatch(ip);
  }

  /// Version améliorée du test de connexion avec plus de logs
  Future<ConnectionTestResult> testConnectionWithDebug({
    Duration timeout = const Duration(seconds: 5),
    int maxRetries = 3,
  }) async {
    // Debug de l'état avant test
    debugCurrentState();

    // Vérifier et recharger si nécessaire
    if (!isConfigured) {
      if (kDebugMode) {
        print("🔄 Configuration non valide, rechargement forcé...");
      }
      
      final reloadSuccess = await forceClearAndReload();
      if (!reloadSuccess) {
        return const ConnectionTestResult(
          isSuccessful: false,
          message: 'Impossible de recharger la configuration',
          status: PrinterConnectionStatus.notConfigured,
          responseTime: Duration.zero,
        );
      }
    }

    if (kDebugMode) {
      print("🎯 Test de connexion vers: ${_settings!.ipAddress}:${_settings!.port}");
    }

    return await testConnection(timeout: timeout, maxRetries: maxRetries);
  }

  /// Test de connexion avancé avec métriques
  Future<ConnectionTestResult> testConnection({
    Duration timeout = const Duration(seconds: 5),
    int maxRetries = 3,
  }) async {
    // Vérifier et recharger la configuration si nécessaire
    if (!isConfigured) {
      if (kDebugMode) {
        print("🔄 Configuration non valide, tentative de rechargement...");
      }
      
      final reloadSuccess = await initialize();
      if (!reloadSuccess) {
        return const ConnectionTestResult(
          isSuccessful: false,
          message: 'Impossible de recharger la configuration imprimante',
          status: PrinterConnectionStatus.notConfigured,
          responseTime: Duration.zero,
        );
      }
    }

    final stopwatch = Stopwatch()..start();

    for (int attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        _connectionStatus = PrinterConnectionStatus.connecting;

        if (kDebugMode) {
          print("🔍 Test de connexion (tentative $attempt/$maxRetries) vers ${_settings!.ipAddress}:${_settings!.port}");
        }

        final socket = await Socket.connect(
          _settings!.ipAddress!,
          _settings!.port!,
        ).timeout(timeout);

        // Test d'écriture simple pour vérifier que l'imprimante répond
        socket.add(ESC_INIT);
        await socket.flush();
        await socket.close();

        stopwatch.stop();
        _connectionStatus = PrinterConnectionStatus.connected;

        final result = ConnectionTestResult(
          isSuccessful: true,
          message: 'Connexion réussie en ${stopwatch.elapsedMilliseconds}ms',
          status: PrinterConnectionStatus.connected,
          responseTime: stopwatch.elapsed,
        );

        if (kDebugMode) {
          print("✅ ${result.message}");
        }

        return result;

      } on SocketException catch (e) {
        if (kDebugMode) {
          print("🔌 Erreur de socket (tentative $attempt): $e");
        }
        
        if (attempt == maxRetries) {
          stopwatch.stop();
          _connectionStatus = PrinterConnectionStatus.disconnected;
          return ConnectionTestResult(
            isSuccessful: false,
            message: 'Imprimante inaccessible: ${e.message}',
            status: PrinterConnectionStatus.disconnected,
            responseTime: stopwatch.elapsed,
          );
        }
        
        // Attendre avant la prochaine tentative
        await Future.delayed(Duration(milliseconds: 500 * attempt));
        
      } on TimeoutException {
        if (kDebugMode) {
          print("⏰ Timeout de connexion (tentative $attempt)");
        }
        
        if (attempt == maxRetries) {
          stopwatch.stop();
          _connectionStatus = PrinterConnectionStatus.disconnected;
          return ConnectionTestResult(
            isSuccessful: false,
            message: 'Timeout de connexion après ${timeout.inSeconds}s',
            status: PrinterConnectionStatus.disconnected,
            responseTime: stopwatch.elapsed,
          );
        }
        
        await Future.delayed(Duration(milliseconds: 500 * attempt));
        
      } catch (e) {
        if (kDebugMode) {
          print("💥 Erreur inattendue (tentative $attempt): $e");
        }
        
        if (attempt == maxRetries) {
          stopwatch.stop();
          _connectionStatus = PrinterConnectionStatus.error;
          return ConnectionTestResult(
            isSuccessful: false,
            message: 'Erreur de connexion: $e',
            status: PrinterConnectionStatus.error,
            responseTime: stopwatch.elapsed,
          );
        }
        
        await Future.delayed(Duration(milliseconds: 500 * attempt));
      }
    }

    // Ce code ne devrait jamais être atteint
    stopwatch.stop();
    _connectionStatus = PrinterConnectionStatus.error;
    return ConnectionTestResult(
      isSuccessful: false,
      message: 'Échec après $maxRetries tentatives',
      status: PrinterConnectionStatus.error,
      responseTime: stopwatch.elapsed,
    );
  }

  /// Test de connexion simple (rétrocompatibilité)
  Future<bool> testConnectionSimple() async {
    final result = await testConnection();
    return result.isSuccessful;
  }

  /// Diagnostic complet de l'imprimante
  Future<Map<String, dynamic>> runDiagnostics() async {
    final diagnostics = <String, dynamic>{
      'timestamp': DateTime.now().toIso8601String(),
      'configured': isConfigured,
      'connectionStatus': _connectionStatus.toString(),
      'lastConfigUpdate': _lastConfigUpdate?.toIso8601String(),
      'configAge': _lastConfigUpdate != null 
          ? DateTime.now().difference(_lastConfigUpdate!).inMinutes 
          : null,
    };

    if (_settings != null) {
      diagnostics['settings'] = {
        'ipAddress': _settings!.ipAddress,
        'port': _settings!.port,
        'name': _settings!.name,
        'type': _settings!.type,
        'id': _settings!.id,
        'createdAt': _settings!.createdAt?.toIso8601String(),
        'updatedAt': _settings!.updatedAt?.toIso8601String(),
      };
    } else {
      diagnostics['settings'] = 'Non configuré';
    }

    if (isConfigured) {
      // Test de résolution DNS (si applicable)
      try {
        final addresses = await InternetAddress.lookup(_settings!.ipAddress!);
        diagnostics['dnsResolution'] = {
          'success': true,
          'addresses': addresses.map((addr) => addr.address).toList(),
        };
      } catch (e) {
        diagnostics['dnsResolution'] = {
          'success': false,
          'error': e.toString(),
        };
      }

      // Test de connectivité
      final connectionResult = await testConnection(maxRetries: 1);
      diagnostics['connectionTest'] = {
        'success': connectionResult.isSuccessful,
        'message': connectionResult.message,
        'responseTime': '${connectionResult.responseTime.inMilliseconds}ms',
        'status': connectionResult.status.toString(),
      };

      // Test de ping réseau (optionnel)
      diagnostics['networkReachability'] = await _testNetworkReachability();
    }

    return diagnostics;
  }

  /// Test de accessibilité réseau
  Future<Map<String, dynamic>> _testNetworkReachability() async {
    try {
      final result = await Process.run('ping', [
        '-c', '1', // Une seule tentative
        '-W', '3000', // Timeout 3 secondes
        _settings!.ipAddress!,
      ]);

      return {
        'success': result.exitCode == 0,
        'output': result.stdout,
        'error': result.stderr,
      };
    } catch (e) {
      return {
        'success': false,
        'error': 'Ping non disponible: $e',
      };
    }
  }

  /// Met à jour la configuration manuellement
  bool updateConfiguration(String ipAddress, int port, {String? name, String? type}) {
    if (!_isValidIpAddress(ipAddress)) {
      if (kDebugMode) {
        print("❌ Adresse IP invalide: $ipAddress");
      }
      return false;
    }

    if (port <= 0 || port > 65535) {
      if (kDebugMode) {
        print("❌ Port invalide: $port");
      }
      return false;
    }

    // Vérifier si c'est un changement
    bool configChanged = _settings == null || 
        _settings!.ipAddress != ipAddress ||
        _settings!.port != port;

    _settings = PrinterSettings(
      ipAddress: ipAddress,
      port: port,
      name: name,
      type: type,
      createdAt: DateTime.now(),
      updatedAt: DateTime.now(),
    );

    _lastConfigUpdate = DateTime.now();
    
    // Réinitialiser le statut si changement
    if (configChanged) {
      _connectionStatus = PrinterConnectionStatus.disconnected;
    }

    if (kDebugMode) {
      print("🔧 Configuration mise à jour: $ipAddress:$port");
      if (name != null) print("📋 Nom: $name");
      if (type != null) print("🏷️ Type: $type");
    }

    return true;
  }

  /// Recharge la configuration depuis l'API
  Future<bool> reloadConfiguration() async {
    if (kDebugMode) {
      print("🔄 Rechargement de la configuration depuis l'API...");
    }
    return await initialize();
  }

  /// Réinitialise la configuration
  void resetConfiguration() {
    _settings = null;
    _connectionStatus = PrinterConnectionStatus.notConfigured;
    _lastConfigUpdate = null;
    
    if (kDebugMode) {
      print("🔄 Configuration de l'imprimante réinitialisée");
    }
  }

  /// Vérifie si la configuration a changé
  bool hasConfigurationChanged(PrinterSettings newSettings) {
    if (_settings == null) return true;
    
    return _settings!.ipAddress != newSettings.ipAddress ||
           _settings!.port != newSettings.port ||
           _settings!.name != newSettings.name ||
           _settings!.type != newSettings.type;
  }

  /// Informations de debug
  Map<String, dynamic> getDebugInfo() {
    return {
      'isConfigured': isConfigured,
      'connectionStatus': _connectionStatus.toString(),
      'lastConfigUpdate': _lastConfigUpdate?.toIso8601String(),
      'configAge': _lastConfigUpdate != null 
          ? DateTime.now().difference(_lastConfigUpdate!).inMinutes 
          : null,
      'settings': _settings != null ? {
        'ipAddress': _settings!.ipAddress,
        'port': _settings!.port,
        'name': _settings!.name,
        'type': _settings!.type,
      } : null,
    };
  }

  /// Méthode pour normaliser les caractères accentués
  String safePadRight(String text, int width) {
    // Remplace temporairement les accents par des lettres simples
    final normalized = text
      .replaceAll(RegExp(r'[éèêë]'), 'e')
      .replaceAll(RegExp(r'[àâä]'), 'a')
      .replaceAll(RegExp(r'[ôö]'), 'o')
      .replaceAll(RegExp(r'[ûü]'), 'u')
      .replaceAll(RegExp(r'[ç]'), 'c')
      .replaceAll(RegExp(r'[ÉÈÊË]'), 'E')
      .replaceAll(RegExp(r'[ÀÂÄ]'), 'A')
      .replaceAll(RegExp(r'[ÔÖ]'), 'O')
      .replaceAll(RegExp(r'[ÛÜ]'), 'U')
      .replaceAll(RegExp(r'[Ç]'), 'C');

    return normalized.padRight(width);
  }

  Future<bool> _ensureValidConfiguration() async {
    if (!isConfigured) {
      if (kDebugMode) {
        print("🔄 Configuration non valide, rechargement...");
      }
      final reloaded = await initialize();
      if (!reloaded) {
        if (kDebugMode) {
          print("❌ Impossible de recharger la configuration imprimante");
        }
        return false;
      }
    }
    return true;
  }

  // Méthodes d'impression optimisées
  Future<bool> printOrderESCPOS(Order order) async {
    if (!await _ensureValidConfiguration()) {
      return false;
    }

    final connectionTest = await testConnection();
    if (!connectionTest.isSuccessful) {
      if (kDebugMode) {
        print("❌ Impossible d'imprimer: ${connectionTest.message}");
      }
      return false;
    }

    try {
      final socket = await Socket.connect(_settings!.ipAddress!, _settings!.port!);
      final List<int> bytes = [];

      // Initialisation et configuration pour 80mm
      bytes.addAll(ESC_INIT);
      bytes.addAll(ESC_PAGE_WIDTH_80MM);
      bytes.addAll(ESC_LEFT_MARGIN_0);
      bytes.addAll(latin1.encode('${'-' * maxCharsPerLine}\n'));
      bytes.addAll(ESC_LEFT_MARGIN_0);
      
      // En-tête centré
      bytes.addAll(ESC_ALIGN_CENTER);
      bytes.addAll(ESC_BOLD_ON);
      bytes.addAll(ESC_LEFT_MARGIN_0);
      bytes.addAll(latin1.encode('Commande n° ${order.numeroCommande}\n'));
     
      // Informations commande
      bytes.addAll(ESC_LEFT_MARGIN_0);
      bytes.addAll(ESC_ALIGN_CENTER);
      bytes.addAll(ESC_NORMAL_SIZE);
      
      bytes.addAll(latin1.encode('Table: ${order.tablename}\n'));
      bytes.addAll(ESC_BOLD_OFF);
      bytes.addAll(latin1.encode('Date: ${_formatTime(order.dateCommande)}\n'));
      bytes.addAll(latin1.encode('${'-' * maxCharsPerLine}\n'));

      // En-tête du tableau
      bytes.addAll(ESC_ALIGN_CENTER);
      bytes.addAll(ESC_BOLD_ON);
      bytes.addAll(ESC_LEFT_MARGIN_0);
      String header = 'Designation'.padRight(maxCharsPerLine - rightWord.length - padding) + 
                     ' ' * padding + rightWord + '\n';
      bytes.addAll(latin1.encode(header));
      bytes.addAll(ESC_BOLD_OFF);
      bytes.addAll(latin1.encode('${'-' * maxCharsPerLine}\n'));

      // Articles
      bytes.addAll(ESC_ALIGN_CENTER);
      bytes.addAll(ESC_LEFT_MARGIN_0);
      for (var item in order.items) {
        String designation = '${item.quantite}x ${item.nom ?? 'Item'}';
        int maxDesignationLength = maxCharsPerLine - checkbox.length - padding;

        if (designation.length > maxDesignationLength) {
          designation = designation.substring(0, maxDesignationLength - 3) + '...';
        }
        
        String line = designation.padRight(maxDesignationLength) + 
                     ' ' * padding + checkbox + '\n';
        bytes.addAll(utf8.encode(line));
      }

      // Pied de page
      bytes.addAll(utf8.encode('${'-' * maxCharsPerLine}\n'));
      
      // Espacement avant coupe
      bytes.addAll([0x0A, 0x0A, 0x0A]);
      bytes.addAll(ESC_CUT);

      socket.add(bytes);
      await socket.flush();
      await socket.close();

      if (kDebugMode) {
        print("✅ Impression réussie!");
      }

      return true;
    } catch (e) {
      if (kDebugMode) {
        print('💥 Erreur impression: $e');
      }
      return false;
    }
  }

  Future<bool> printOrderESC80MM(Order order) async {
    // Auto-revalidation avant impression
    if (!await _ensureValidConfiguration()) {
      return false;
    }

    final connectionTest = await testConnection();
    if (!connectionTest.isSuccessful) {
      if (kDebugMode) {
        print("❌ Impossible d'imprimer: ${connectionTest.message}");
      }
      return false;
    }

    try {
      final socket = await Socket.connect(_settings!.ipAddress!, _settings!.port!);
      final List<int> bytes = [];

      // Configuration spécifique 80mm
      bytes.addAll(ESC_INIT);
      bytes.addAll(ESC_PAGE_WIDTH_80MM);
      bytes.addAll(ESC_LEFT_MARGIN_0);
      
      // En-tête centré et stylisé
      bytes.addAll(ESC_ALIGN_CENTER);
      bytes.addAll(ESC_DOUBLE_SIZE);
      bytes.addAll(ESC_BOLD_ON);
      bytes.addAll(ESC_PAGE_WIDTH_80MM);
      bytes.addAll(utf8.encode('COMMANDE\n'));
      bytes.addAll(ESC_BOLD_OFF);
      bytes.addAll(ESC_NORMAL_SIZE);
      bytes.addAll(utf8.encode('${'-' * maxCharsPerLine}\n'));

      // Informations commande avec formatage amélioré
      bytes.addAll(utf8.encode(_createInfoLine('N° Commande', order.numeroCommande.toString())));
      bytes.addAll(utf8.encode(_createInfoLine('Date/Heure', _formatTime(order.dateCommande))));
      bytes.addAll(utf8.encode('${'=' * maxCharsPerLine}\n'));

      // En-tête du tableau avec colonnes bien définies
      bytes.addAll(ESC_BOLD_ON);
      bytes.addAll(ESC_PAGE_WIDTH_80MM);
      bytes.addAll(utf8.encode(_createTableHeader()));
      bytes.addAll(ESC_BOLD_OFF);
      bytes.addAll(utf8.encode('${'-' * maxCharsPerLine}\n'));

      // Articles avec formatage en colonnes
      for (var item in order.items) {
        bytes.addAll(utf8.encode(_createItemLine(item.quantite, item.nom ?? 'Item')));
      }

      // Pied de page
      bytes.addAll(utf8.encode('${'=' * maxCharsPerLine}\n'));
      bytes.addAll(ESC_ALIGN_CENTER);
      bytes.addAll(ESC_PAGE_WIDTH_80MM);
      
      // Coupe avec espacement
      bytes.addAll([0x0A, 0x0A]);
      bytes.addAll(ESC_CUT);

      socket.add(bytes);
      await socket.flush();
      await socket.close();

      return true;
    } catch (e) {
      if (kDebugMode) {
        print('Erreur impression: $e');
      }
      return false;
    }
  }

  Future<bool> printOrderESCPOSOptimized(Order order) async {
    if (!await _ensureValidConfiguration()) {
      return false;
    }

    final connectionTest = await testConnection();
    if (!connectionTest.isSuccessful) {
      if (kDebugMode) {
        print("❌ Impossible d'imprimer: ${connectionTest.message}");
      }
      return false;
    }

    try {
      final socket = await Socket.connect(_settings!.ipAddress!, _settings!.port!);
      final List<int> bytes = [];

      // Configuration initiale optimisée pour 72mm
      bytes.addAll(ESC_INIT);
      bytes.addAll(ESC_LEFT_MARGIN_0);
      
      // Définir largeur de page explicite
      bytes.addAll([0x1B, 0x51, 180]);
      
      // En-tête
      bytes.addAll(ESC_ALIGN_CENTER);
      bytes.addAll(ESC_DOUBLE_SIZE);
      bytes.addAll(utf8.encode('COMMANDE\n\n'));

      // Corps avec police condensée
      bytes.addAll(ESC_NORMAL_SIZE);
      bytes.addAll(ESC_CONDENSED_ON);
      
      const int compactMaxChars = 32;
      
      bytes.addAll(utf8.encode('Cmd: ${order.numeroCommande}\n'));
      bytes.addAll(utf8.encode('Table: ${order.tablename}\n'));
      bytes.addAll(utf8.encode('${_formatTime(order.dateCommande)}\n'));
      bytes.addAll(utf8.encode('${'=' * compactMaxChars}\n'));

      // Articles avec formatage optimisé
      for (var item in order.items) {
        String qty = '${item.quantite}x';
        String name = item.nom ?? 'Item';
        int availableSpace = compactMaxChars - qty.length - checkbox.length - 2;
        
        if (name.length > availableSpace) {
          name = name.substring(0, availableSpace - 3) + '...';
        }
        
        String line = '$qty $name'.padRight(compactMaxChars - checkbox.length) + checkbox + '\n';
        bytes.addAll(utf8.encode(line));
      }

      // Finalisation
      bytes.addAll(utf8.encode('${'=' * compactMaxChars}\n'));
      bytes.addAll(ESC_CONDENSED_OFF);
      bytes.addAll(ESC_ALIGN_CENTER);
      bytes.addAll(utf8.encode('\nBon service !\n\n\n'));
      bytes.addAll(ESC_CUT);

      socket.add(bytes);
      await socket.flush();
      await socket.close();

      return true;
    } catch (e) {
      if (kDebugMode) {
        print('Erreur impression: $e');
      }
      return false;
    }
  }

  // Fonctions utilitaires pour formatage
  String _createInfoLine(String label, String value) {
    int labelWidth = 12;
    int valueWidth = maxCharsPerLine - labelWidth - 2;
    
    String truncatedLabel = label.length > labelWidth ? 
        label.substring(0, labelWidth) : label.padRight(labelWidth);
    String truncatedValue = value.length > valueWidth ? 
        value.substring(0, valueWidth - 3) + '...' : value;
    
    return '$truncatedLabel: $truncatedValue\n';
  }

  String _createTableHeader() {
    int qtyWidth = 4;
    int checkboxWidth = checkbox.length;
    int nameWidth = maxCharsPerLine - qtyWidth - checkboxWidth - 2;
    
    String header = 'Qty'.padRight(qtyWidth) + 
                   'Designation'.padRight(nameWidth) + 
                   checkbox + '\n';
    return header;
  }

  String _createItemLine(int quantity, String itemName) {
    int qtyWidth = 4;
    int checkboxWidth = checkbox.length;
    int nameWidth = maxCharsPerLine - qtyWidth - checkboxWidth - 2;
    
    String qtyStr = quantity.toString().padRight(qtyWidth);
    String nameStr = itemName.length > nameWidth ? 
        itemName.substring(0, nameWidth - 3) + '...' : itemName.padRight(nameWidth);
    
    return qtyStr + nameStr + checkbox + '\n';
  }

  /// Formatage du temps
  String _formatTime(DateTime dateTime) {
    return '${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')} ${dateTime.day.toString().padLeft(2, '0')}/${dateTime.month.toString().padLeft(2, '0')}/${dateTime.year}';
  }
}

// Fonction utilitaire pour forcer la mise à jour
Future<bool> forceUpdatePrinterConfig() async {
  final printer = OrderPrinter.instance;
  
  if (kDebugMode) {
    print("🔧 Forçage de la mise à jour de configuration...");
  }
  
  // Méthode 1: Utiliser forceClearAndReload
  bool success = await printer.forceClearAndReload();
  
  if (success) {
    if (kDebugMode) {
      print("✅ Configuration mise à jour avec succès");
    }
    return true;
  } else {
    if (kDebugMode) {
      print("❌ Échec de la mise à jour, tentative de réinitialisation complète...");
    }
    
    // Méthode 2: Réinitialisation complète de l'instance
    OrderPrinter.resetInstance();
    
    // Obtenir la nouvelle instance et initialiser
    final newPrinter = OrderPrinter.instance;
    return await newPrinter.initialize();
  }
}

// Fonction pour tester avec débogage complet
Future<void> testPrinterWithFullDebug() async {
  final printer = OrderPrinter.instance;
  
  print("🔍 === DÉBOGAGE COMPLET IMPRIMANTE ===");
  
  // État initial
  printer.debugCurrentState();
  
  // Force la mise à jour
  print("🔄 Forçage de la mise à jour...");
  await printer.forceClearAndReload();
  
  // État après mise à jour
  print("📊 État après mise à jour:");
  printer.debugCurrentState();
  
  // Test de connexion
  print("🔗 Test de connexion...");
  final result = await printer.testConnectionWithDebug();
  
  print("📋 Résultat: ${result.isSuccessful ? '✅' : '❌'} ${result.message}");
  
  // Diagnostic complet
  print("🏥 Diagnostic complet:");
  final diagnostics = await printer.runDiagnostics();
  diagnostics.forEach((key, value) {
    print("   $key: $value");
  });
}

// Fonctions utilitaires pour rétrocompatibilité
Future<bool> printOrderPDF(Order order) async {
  final printer = OrderPrinter.instance;
  
  // Initialiser si nécessaire
  if (!printer.isConfigured) {
    final initialized = await printer.initialize();
    if (!initialized) {
      if (kDebugMode) {
        print('❌ Impossible d\'initialiser l\'imprimante');
      }
      return false;
    }
  }

  return await printer.printOrderESC80MM(order);
}

Future<void> printOrderWithFeedback(Order order, Function(String, bool) onResult) async {
  final printer = OrderPrinter.instance;

  try {
    // Initialisation si nécessaire
    if (!printer.isConfigured) {
      onResult('Initialisation de l\'imprimante...', true);
      final initialized = await printer.initialize();
      if (!initialized) {
        onResult('Échec de l\'initialisation', false);
        return;
      }
    }

    // Test de connexion
    onResult('Test de connexion...', true);
    final connectionResult = await printer.testConnection();

    if (!connectionResult.isSuccessful) {
      onResult(connectionResult.message, false);
      return;
    }

    // Impression
    onResult('Impression en cours...', true);
    final success = await printer.printOrderESCPOS(order);

    if (success) {
      onResult('Impression réussie!', true);
    } else {
      onResult('Échec de l\'impression', false);
    }
  } catch (e) {
    onResult('Erreur: $e', false);
  }
}

// Fonction utilitaire pour obtenir des informations sur l'imprimante
Future<Map<String, dynamic>> getPrinterInfo() async {
  final printer = OrderPrinter.instance;
  
  if (!printer.isConfigured) {
    await printer.initialize();
  }

  return await printer.runDiagnostics();
}

// Fonction pour tester la connexion avec retour détaillé
Future<ConnectionTestResult> testPrinterConnection() async {
  final printer = OrderPrinter.instance;
  
  if (!printer.isConfigured) {
    await printer.initialize();
  }

  return await printer.testConnection();
}