import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:intl/intl.dart';
import 'package:cashumit/models/receipt_item.dart';
import 'package:flutter_esc_pos_utils/flutter_esc_pos_utils.dart';
import 'package:image/image.dart' as img;
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

/// Service untuk menghasilkan perintah ESC/POS menggunakan flutter_esc_pos_utils
class EscPosPrintService {
  /// Menghasilkan struk dalam format byte array berdasarkan data transaksi
  static Future<List<int>> generateEscPosBytes({
    required List<ReceiptItem> items,
    required DateTime transactionDate,
    required String cashierId,
    required String transactionId,
  }) async {
    print('Memulai generateEscPosBytes...');
    print('Jumlah item: ${items.length}');
    print('Tanggal transaksi: $transactionDate');
    print('ID kasir: $cashierId');
    print('ID transaksi: $transactionId');
    
    // Load store info from shared preferences
    final prefs = await SharedPreferences.getInstance();
    final storeName = prefs.getString('store_name') ?? 'TOKO SEMBAKO MURAH';
    final storeAddress = prefs.getString('store_address') ?? 'Jl. Merdeka No. 123';
    final adminName = prefs.getString('admin_name') ?? 'Budi Santoso';
    final adminPhone = prefs.getString('admin_phone') ?? '08123456789';
    
    print('Nama toko: $storeName');
    print('Alamat toko: $storeAddress');
    print('Nama admin: $adminName');
    print('Telepon admin: $adminPhone');
    
    // Format tanggal
    final dateFormatter = DateFormat('dd/MM/yyyy HH:mm');
    final formattedDate = dateFormatter.format(transactionDate);
    print('Tanggal yang diformat: $formattedDate');
    
    // Format angka ke rupiah
    String formatRupiah(double amount) {
      final formatter = NumberFormat("#,##0", "id_ID");
      return "Rp ${formatter.format(amount)}";
    }
    
    // Load capability profile with timeout
    CapabilityProfile profile;
    try {
      profile = await CapabilityProfile.load();
    } catch (e) {
      print('Gagal memuat capability profile: $e');
      // Gunakan profile default jika gagal
      profile = await CapabilityProfile.load();
    }
    
    final generator = Generator(PaperSize.mm58, profile);
    
    // Mulai dengan inisialisasi printer
    List<int> bytes = [];

    // Coba tambahkan logo toko jika ada
    final logoPath = prefs.getString('store_logo_path');
    if (logoPath != null && logoPath.isNotEmpty) {
      try {
        final img.Image? logo = await getImageFromFilePath(logoPath);
        if (logo != null) {
          // Mengubah ukuran logo agar pas di struk (lebar maks 300px)
          final resizedLogo = img.copyResize(logo, width: 300);
          bytes += generator.image(resizedLogo, align: PosAlign.center);
          bytes += generator.feed(1); // Beri sedikit spasi setelah logo
        }
      } catch (e) {
        print('Error loading or processing store logo: $e');
      }
    }
    
    // Tambahkan nama toko sebagai header
    bytes += generator.text(storeName,
        styles: PosStyles(
          bold: true,
          height: PosTextSize.size1,
          width: PosTextSize.size1,
          align: PosAlign.center,
        ));
    
    try {
      bytes += generator.text(storeAddress,
          styles: PosStyles(align: PosAlign.center));
      bytes += generator.text('Admin: $adminName',
          styles: PosStyles(align: PosAlign.center));
      bytes += generator.text('Telp: $adminPhone',
          styles: PosStyles(align: PosAlign.center));
      bytes += generator.text('$formattedDate',
          styles: PosStyles(align: PosAlign.center));
      
      bytes += generator.feed(1);
      
      // Garis pemisah
      bytes += generator.text('================================',
          styles: PosStyles(align: PosAlign.center));
      
      // Informasi transaksi
      bytes += generator.text('Kasir: $cashierId',
          styles: PosStyles(bold: true));
      bytes += generator.text('ID Transaksi: $transactionId',
          styles: PosStyles());
      
      bytes += generator.feed(1);
      
      // Garis pemisah
      bytes += generator.text('================================',
          styles: PosStyles(align: PosAlign.center));
      
      // Tabel item
      bytes += generator.row([
        PosColumn(
          text: 'Item',
          width: 7,
          styles: PosStyles(bold: true, align: PosAlign.left),
        ),
        PosColumn(
          text: 'Total',
          width: 5,
          styles: PosStyles(bold: true, align: PosAlign.right),
        ),
      ]);
      
      // Item list dengan penanganan error
      print('Memulai iterasi item...');
      for (int i = 0; i < items.length; i++) {
        try {
          var item = items[i];
          print('Item $i: ${item.description}, qty: ${item.quantity}, price: ${item.price}, total: ${item.total}');
          
          // Untuk item dengan detail kuantitas dan harga
          bytes += generator.row([
            PosColumn(
              text: item.description,
              width: 12,
              styles: PosStyles(align: PosAlign.left),
            ),
          ]);
          
          bytes += generator.row([
            PosColumn(
              text: '${item.quantity} x ${formatRupiah(item.price)}',
              width: 7,
              styles: PosStyles(align: PosAlign.left, height: PosTextSize.size1, width: PosTextSize.size1),
            ),
            PosColumn(
              text: formatRupiah(item.total),
              width: 5,
              styles: PosStyles(align: PosAlign.right),
            ),
          ]);
        } catch (e) {
          print('Error saat memproses item $i: $e');
          // Lanjutkan ke item berikutnya jika ada error
          continue;
        }
      }
      print('Selesai iterasi item');
      
      // Garis pemisah sebelum total
      bytes += generator.text('--------------------------------',
          styles: PosStyles(align: PosAlign.center));
      
      // Total
      double totalAmount = 0.0;
      try {
        totalAmount = items.fold(0.0, (sum, item) => sum + item.total);
      } catch (e) {
        print('Error saat menghitung total: $e');
        totalAmount = 0.0;
      }
      
      print('Total amount: $totalAmount');
      
      bytes += generator.row([
        PosColumn(
          text: 'TOTAL',
          width: 7,
          styles: PosStyles(bold: true, align: PosAlign.left),
        ),
        PosColumn(
          text: formatRupiah(totalAmount),
          width: 5,
          styles: PosStyles(bold: true, align: PosAlign.right),
        ),
      ]);
      
      // Garis pemisah setelah total
      bytes += generator.text('================================',
          styles: PosStyles(align: PosAlign.center));

      // Memuat teks kustom dari shared preferences
      String customDisclaimer;
      try {
        customDisclaimer = prefs.getString('store_disclaimer_text') ?? 
            'Barang yang sudah dibeli tidak dapat dikembalikan/ditukar. ' 
            'Harap periksa kembali struk belanja Anda sebelum meninggalkan toko.';
      } catch (e) {
        print('Error saat memuat disclaimer: $e');
        customDisclaimer = 'Barang yang sudah dibeli tidak dapat dikembalikan/ditukar.';
      }
      
      String customThankYou;
      try {
        customThankYou = prefs.getString('thank_you_text') ?? '*** TERIMA KASIH ***';
      } catch (e) {
        print('Error saat memuat thank you text: $e');
        customThankYou = '*** TERIMA KASIH ***';
      }
      
      String customPantun;
      try {
        customPantun = prefs.getString('pantun_text') ?? 
            'Belanja di toko kami, hemat dan nyaman\n'
            'Dengan penuh semangat, kami siap melayani\n'
            'Harapan kami, Anda selalu puas\n'
            'Sampai jumpa lagi, selamat tinggal.';
      } catch (e) {
        print('Error saat memuat pantun: $e');
        customPantun = '';
      }

      // Menambahkan disclaimer
      bytes += generator.feed(1);
      
      // Memecah disclaimer menjadi beberapa baris jika terlalu panjang
      try {
        final disclaimerLines = customDisclaimer.split(' ');
        final List<String> wrappedDisclaimer = [];
        String currentLine = '';

        for (final word in disclaimerLines) {
          if ((currentLine + word).length > 32) {
            wrappedDisclaimer.add(currentLine.trim());
            currentLine = word + ' ';
          } else {
            currentLine += word + ' ';
          }
        }
        if (currentLine.trim().isNotEmpty) {
          wrappedDisclaimer.add(currentLine.trim());
        }

        for (final line in wrappedDisclaimer) {
          bytes += generator.text(line,
              styles: PosStyles(align: PosAlign.center));
        }
      } catch (e) {
        print('Error saat memproses disclaimer: $e');
        // Fallback jika ada error
        bytes += generator.text(customDisclaimer,
            styles: PosStyles(align: PosAlign.center));
      }

      // Menambahkan ucapan terima kasih
      bytes += generator.feed(1);
      bytes += generator.text(customThankYou,
          styles: PosStyles(align: PosAlign.center, bold: true));

      // Menambahkan pantun jika ada
      if (customPantun.isNotEmpty) {
        try {
          bytes += generator.feed(1);
          final pantunLines = customPantun.split('\n');
          for (final line in pantunLines) {
            bytes += generator.text(line,
                styles: PosStyles(align: PosAlign.center));
          }
        } catch (e) {
          print('Error saat menambahkan pantun: $e');
        }
      }

      // Spasi di akhir dan pemotongan kertas
      bytes += generator.feed(2);
      bytes += generator.cut();
    } catch (e) {
      print('Error saat membuat bagian akhir struk: $e');
      // Pastikan struk tetap dipotong meski ada error
      bytes += generator.feed(2);
      bytes += generator.cut();
    }
    
    print('Jumlah byte yang dihasilkan: ${bytes.length}');
    
    return bytes;
  }

  /// Mencetak struk ke printer thermal
  static Future<void> printToThermalPrinter({
    required List<ReceiptItem> items,
    required DateTime transactionDate,
    required BuildContext context,
    required dynamic bluetoothService, // Kita akan sesuaikan tipe ini nanti
  }) async {
    // Definisikan cashierId dan transactionId di sini karena tidak berubah
    final String cashierId = 'KSR001';
    final String transactionId = 'TXN202508200001';
    
    print('=== FUNGSI printToThermalPrinter DIPANGGIL ===');
    print('Memulai proses pencetakan struk...');
    print('Jumlah item: ${items.length}');
    print('Tanggal transaksi: ${transactionDate}');
    print('ID kasir: $cashierId');
    print('ID transaksi: $transactionId');
    
    try {
      print('Menghasilkan byte array ESC/POS menggunakan flutter_esc_pos_utils...');
      print('Jumlah item: ${items.length}');
      print('Tanggal transaksi: ${transactionDate}');
      print('ID kasir: $cashierId');
      print('ID transaksi: $transactionId');
      
      // Generate struk dalam format byte array menggunakan EscPosPrintService
      final bytes = await generateEscPosBytes(
        items: items,
        transactionDate: transactionDate,
        cashierId: cashierId,
        transactionId: transactionId,
      );
      
      print('Byte array ESC/POS berhasil dihasilkan');
      print('Jumlah byte: ${bytes.length}');

      // Tampilkan byte array untuk debugging (dalam format hex)
      print('Isi byte array (hex):');
      if (bytes.length <= 1000) { // Batasi tampilan untuk mencegah output terlalu panjang
        print(bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(' '));
      } else {
        print('Terlalu banyak byte untuk ditampilkan (${bytes.length} bytes)');
      }

      // Verifikasi koneksi sebelum mencetak
      final isConnectedBeforePrint = await bluetoothService.checkConnection();
      if (!isConnectedBeforePrint) {
        print('Printer tidak terhubung saat akan mencetak');
        throw Exception('Printer tidak terhubung saat akan mencetak');
      }
      
      print('Mengirim byte array ke printer...');
      
      try {
        // Konversi List<int> ke Uint8List
        final Uint8List data = Uint8List.fromList(bytes);
        await bluetoothService.printReceipt(data);
        print('Perintah cetak berhasil dikirim');
      } catch (printError) {
        print('Error saat mengirim perintah cetak ke printer: $printError');
        throw Exception('Gagal mengirim perintah cetak: $printError');
      }
    } catch (e, stackTrace) {
      print('Error saat mencetak struk: $e');
      print('Stack trace: $stackTrace');
      // Cetak detail error tambahan
      print('Tipe error: ${e.runtimeType}');
      throw Exception('Gagal mencetak struk: $e');
    }
  }

  /// Helper function to get image from file path
  static Future<img.Image?> getImageFromFilePath(String path) async {
    try {
      final file = File(path);
      if (await file.exists()) {
        final bytes = await file.readAsBytes();
        return img.decodeImage(bytes);
      }
    } catch (e) {
      print('Error getting image from file path: $e');
    }
    return null;
  }
}
