import 'package:esc_pos_utils_plus/esc_pos_utils_plus.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:http/http.dart' as http;
import 'package:image/image.dart' as img;
import 'package:image/image.dart';
import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart';
import 'package:intl/intl.dart';
import 'package:nb_utils/nb_utils.dart';
import 'package:print_bluetooth_thermal/print_bluetooth_thermal.dart';

import '../Provider/network_image.dart';
import '../WAVE PRINTER/wave_printer_functions.dart';
import '../constant.dart';
import '../model/print_transaction_model.dart';

class PurchaseReturnInvoiceThermal {
  void printPurchaseTicket(
      {required PrintPurchaseReturnTransactionModel printTransactionModel}) async {
    bool? isConnected = await PrintBluetoothThermal.connectionStatus;
    if (isConnected == true) {
      List<int> bytes = (printTransactionModel.personalInformationModel.thermalPrinterPrintSize ==
                  '3 Inch (80 mm)' &&
              printTransactionModel.personalInformationModel.thermalPrinterPrintSize != null)
          ? await getPurchase80mmTicket(printTransactionModel: printTransactionModel)
          : await getPurchase58mmTicket(printTransactionModel: printTransactionModel);
      if (printTransactionModel.purchaseTransactionModel?.productList!.isNotEmpty ?? false) {
        await PrintBluetoothThermal.writeBytes(bytes);
      } else {
        toast('No Product Found');
      }
    } else {
      EasyLoading.showError('Unable to connect with printer');
    }
  }

  Future<List<int>> getPurchase58mmTicket(
      {required PrintPurchaseReturnTransactionModel printTransactionModel}) async {
    List<int> bytes = [];

    CapabilityProfile profile = await CapabilityProfile.load();
    final generator = Generator(PaperSize.mm58, profile);

    ///__________Shop_logo_________________________________________
    bool result = await InternetConnection().hasInternetAccess;
    if (result) {
      http.Response response = await http.get(
        Uri.parse(printTransactionModel.personalInformationModel.pictureUrl ?? ''),
      );
      response.bodyBytes;
      final decodedImage = img.decodeImage(response.bodyBytes);
      final resizedImage = img.copyResize(decodedImage!, width: 120, height: 120); //Uint8List
      final encodedImage = img.encodeJpg(resizedImage);
      Uint8List byteList = Uint8List.fromList(encodedImage);
      final Uint8List imageBytes = byteList;
      bytes += generator.image(decodeImage(imageBytes)!);
    }
    bytes += generator.text(printTransactionModel.personalInformationModel.companyName ?? '',
        styles: const PosStyles(
          align: PosAlign.center,
          height: PosTextSize.size2,
          width: PosTextSize.size2,
        ),
        linesAfter: 1);

    bytes += generator.text(printTransactionModel.personalInformationModel.countryName ?? '',
        styles: const PosStyles(align: PosAlign.center));
    bytes += generator.text(
        'Tel: ${printTransactionModel.personalInformationModel.phoneNumber ?? ''}',
        styles: const PosStyles(align: PosAlign.center),
        linesAfter: printTransactionModel.personalInformationModel.gst.trim().isNotEmpty ? 0 : 1);
    printTransactionModel.personalInformationModel.gst.trim().isNotEmpty
        ? bytes += generator.text(
            'Shop ${printTransactionModel.personalInformationModel.gstOrTinNameType == "" ? 'GST' : printTransactionModel.personalInformationModel.gstOrTinNameType}: ${printTransactionModel.personalInformationModel.gst ?? ''}',
            styles: const PosStyles(align: PosAlign.center),
            linesAfter: 1)
        : null;
    bytes += generator.text(
        'Name: ${printTransactionModel.purchaseTransactionModel?.customerName ?? 'Guest'}',
        styles: const PosStyles(align: PosAlign.left));
    bytes += generator.text(
        'Mobile: ${printTransactionModel.purchaseTransactionModel?.customerPhone ?? 'Not Provided'}',
        styles: const PosStyles(align: PosAlign.left));
    (printTransactionModel.purchaseTransactionModel?.customerGst.trim().isNotEmpty ?? false)
        ? bytes += generator.text(
            'Party ${printTransactionModel.personalInformationModel.gstOrTinNameType == "" ? 'GST' : printTransactionModel.personalInformationModel.gstOrTinNameType}: ${printTransactionModel.purchaseTransactionModel?.customerGst ?? 'Not Provided'}',
            styles: const PosStyles(align: PosAlign.left))
        : null;
    bytes += generator.text(
        'Invoice: ${printTransactionModel.purchaseTransactionModel?.invoiceNumber ?? 'N/A'}',
        styles: const PosStyles(align: PosAlign.left));
    bytes += generator.text(
      'Date: ${DateFormat.yMd().format(DateTime.parse(printTransactionModel.purchaseTransactionModel?.purchaseDate ?? DateTime.now().toString()))} ${DateFormat.jm().format(DateTime.parse(printTransactionModel.purchaseTransactionModel?.purchaseDate ?? DateTime.now().toString()))}',
      styles: const PosStyles(align: PosAlign.left),
    );
    bytes += generator.hr();
    bytes +=
        generator.text('Items        Rate   Qty    Total', styles: const PosStyles(bold: true));
    bytes += generator.hr();
    bytes += await productTable(
        productList: [],
        purchaseProduct: printTransactionModel.purchaseTransactionModel?.productList ?? [],
        isFour: false);
    bytes += generator.hr();
    bytes += generator.row([
      PosColumn(
          text: 'Subtotal',
          width: 8,
          styles: const PosStyles(
            align: PosAlign.left,
          )),
      PosColumn(
          text:
              '${printTransactionModel.purchaseTransactionModel!.totalAmount!.toDouble() + printTransactionModel.purchaseTransactionModel!.discountAmount!.toDouble()}',
          width: 4,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
    ]);
    bytes += generator.row([
      PosColumn(
          text: 'Discount',
          width: 8,
          styles: const PosStyles(
            align: PosAlign.left,
          )),
      PosColumn(
          text: printTransactionModel.purchaseTransactionModel?.discountAmount.toString() ?? '',
          width: 4,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
    ]);
    bytes += generator.hr();
    bytes += generator.row([
      PosColumn(
          text: 'Total Return Amount:',
          width: 8,
          styles: const PosStyles(align: PosAlign.left, bold: true)),
      PosColumn(
          text: printTransactionModel.purchaseTransactionModel?.totalAmount.toString() ?? '',
          width: 4,
          styles: const PosStyles(align: PosAlign.right, bold: true)),
    ]);

    // bytes += generator.hr(ch: '=', linesAfter: 1);
    // bytes += generator.hr();

    // bytes += generator.row([
    //   PosColumn(
    //     text: 'Payment Type:',
    //     width: 8,
    //     styles: const PosStyles(
    //       align: PosAlign.left,
    //     ),
    //   ),
    //   PosColumn(
    //       text: printTransactionModel.purchaseTransactionModel?.paymentType ?? 'Cash',
    //       width: 4,
    //       styles: const PosStyles(
    //         align: PosAlign.right,
    //       )),
    // ]);
    // bytes += generator.row([
    //   PosColumn(
    //       text: 'Payment Amount:',
    //       width: 8,
    //       styles: const PosStyles(
    //         align: PosAlign.left,
    //       )),
    //   PosColumn(
    //       text: '${printTransactionModel.purchaseTransactionModel!.totalAmount!.toDouble() - printTransactionModel.purchaseTransactionModel!.dueAmount!.toDouble()}',
    //       width: 4,
    //       styles: const PosStyles(
    //         align: PosAlign.right,
    //       )),
    // ]);
    // bytes += generator.row([
    //   PosColumn(
    //       text: 'Return amount:',
    //       width: 8,
    //       styles: const PosStyles(
    //         align: PosAlign.left,
    //       )),
    //   PosColumn(
    //       text: printTransactionModel.purchaseTransactionModel!.returnAmount.toString(),
    //       width: 4,
    //       styles: const PosStyles(
    //         align: PosAlign.right,
    //       )),
    // ]);
    // bytes += generator.row([
    //   PosColumn(
    //       text: 'Due Amount:',
    //       width: 8,
    //       styles: const PosStyles(
    //         align: PosAlign.left,
    //       )),
    //   PosColumn(
    //       text: printTransactionModel.purchaseTransactionModel!.dueAmount.toString(),
    //       width: 4,
    //       styles: const PosStyles(
    //         align: PosAlign.right,
    //       )),
    // ]);
    bytes += generator.hr(ch: '=', linesAfter: 1);

    bytes +=
        generator.text('Thank you!', styles: const PosStyles(align: PosAlign.center, bold: true));

    bytes += generator.text(printTransactionModel.purchaseTransactionModel!.purchaseDate,
        styles: const PosStyles(align: PosAlign.center), linesAfter: 1);

    bytes += generator.text('Note: Goods once sold will not be taken back or exchanged.',
        styles: const PosStyles(align: PosAlign.center, bold: false), linesAfter: 1);

    bytes += generator.text('Developed By: $invoiceName',
        styles: const PosStyles(align: PosAlign.center), linesAfter: 1);
    bytes += generator.cut();
    return bytes;
  }

  Future<List<int>> getPurchase80mmTicket(
      {required PrintPurchaseReturnTransactionModel printTransactionModel}) async {
    // bool isVatAddedBool = isVatAdded(products: productList ?? []);
    List<int> bytes = [];
    CapabilityProfile profile = await CapabilityProfile.load();

    final generator = Generator(PaperSize.mm80, profile);

    ///____________Image__________________________________
    bool result = await InternetConnection().hasInternetAccess;
    if (result) {
      final logo =
          await getNetworkImage(printTransactionModel.personalInformationModel.pictureUrl ?? '');
      if (logo != null) {
        final img.Image resized = img.copyResize(
          logo,
          width: 184,
        );
        final img.Image grayscale = img.grayscale(resized);
        bytes += generator.imageRaster(grayscale, imageFn: PosImageFn.bitImageRaster);
      }
    }

    ///____________Header______________________________________________________________
    bytes += generator.text(printTransactionModel.personalInformationModel.companyName ?? '',
        styles: const PosStyles(
          align: PosAlign.center,
          height: PosTextSize.size2,
          width: PosTextSize.size2,
        ),
        linesAfter: 1);
    if (printTransactionModel.personalInformationModel.countryName != null) {
      bytes += generator.text(
          'Address: ${printTransactionModel.personalInformationModel.countryName}',
          styles: const PosStyles(align: PosAlign.center));
    }
    if (printTransactionModel.personalInformationModel.phoneNumber != null) {
      bytes += generator.text(
          'Mobile: ${printTransactionModel.personalInformationModel.phoneNumber}',
          styles: const PosStyles(align: PosAlign.center));
    }
    bytes += generator.emptyLines(1);
    bytes += generator.text('INVOICE',
        styles: const PosStyles(
          bold: true,
          underline: true,
          align: PosAlign.center,
          height: PosTextSize.size2,
          width: PosTextSize.size2,
        ),
        linesAfter: 1);

    ///__________Customer_and_time_section_______________________
    bytes += generator.row([
      PosColumn(
          text:
              'Purchase Invoice: ${printTransactionModel.purchaseTransactionModel?.invoiceNumber ?? 'Not Provided'}',
          width: 6,
          styles: const PosStyles(align: PosAlign.left)),
      PosColumn(
          text:
              'Date: ${DateFormat.yMd().format(DateTime.parse(printTransactionModel.purchaseTransactionModel?.purchaseDate ?? DateTime.now().toString()))}',
          width: 6,
          styles: const PosStyles(align: PosAlign.right)),
    ]);
    bytes += generator.row([
      PosColumn(
          text: 'Name: ${printTransactionModel.purchaseTransactionModel?.customerName ?? ''}',
          width: 6,
          styles: const PosStyles(align: PosAlign.left)),
      PosColumn(
          text:
              'Time: ${DateFormat.jm().format(DateTime.parse(printTransactionModel.purchaseTransactionModel?.purchaseDate ?? DateTime.now().toString()))}',
          width: 6,
          styles: const PosStyles(align: PosAlign.right)),
    ]);
    bytes += generator.row([
      PosColumn(
          text: 'Mobile: ${printTransactionModel.purchaseTransactionModel?.customerPhone ?? ''}',
          width: 6,
          styles: const PosStyles(align: PosAlign.left)),
      PosColumn(
          text: 'Purchase By: ${'Admin'}',
          width: 6,
          styles: const PosStyles(align: PosAlign.right)),
    ]);

    bytes += generator.emptyLines(1);

    ///____________Products_Section_____________________________________________________
    bytes += generator.hr();
    bytes += generator.row([
      PosColumn(text: 'SL', width: 1, styles: const PosStyles(align: PosAlign.left, bold: true)),
      PosColumn(text: 'Item', width: 5, styles: const PosStyles(align: PosAlign.left, bold: true)),
      PosColumn(
          text: 'Qty', width: 2, styles: const PosStyles(align: PosAlign.center, bold: true)),
      PosColumn(
          text: 'Price', width: 2, styles: const PosStyles(align: PosAlign.center, bold: true)),
      PosColumn(
          text: 'Amount', width: 2, styles: const PosStyles(align: PosAlign.right, bold: true)),
    ]);
    bytes += generator.hr();
    List.generate(printTransactionModel.purchaseTransactionModel?.productList?.length ?? 1,
        (index) {
      final product = printTransactionModel.purchaseTransactionModel?.productList?[index];
      return bytes += generator.row([
        PosColumn(
            text: '${index + 1}',
            width: 1,
            styles: const PosStyles(
              align: PosAlign.left,
            )),
        PosColumn(
            text: product?.productName ?? '',
            width: 5,
            styles: const PosStyles(
              align: PosAlign.left,
            )),
        PosColumn(
            text: formatPointNumber(num.tryParse(product?.productStock.toString() ?? '') ?? 0,
                addComma: true),
            width: 2,
            styles: const PosStyles(align: PosAlign.center)),
        PosColumn(
            text: formatPointNumber(
                num.tryParse(product?.productPurchasePrice.toString() ?? '') ?? 0,
                addComma: true),
            width: 2,
            styles: const PosStyles(
              align: PosAlign.center,
            )),
        PosColumn(
            text: formatPointNumber(
                (double.tryParse(product?.productPurchasePrice.toString() ?? '') ?? 0) *
                    (num.tryParse(product?.productStock ?? '') ?? 0),
                addComma: true),
            width: 2,
            styles: const PosStyles(align: PosAlign.right)),
      ]);
    });
    bytes += generator.hr();

    bytes += generator.row([
      PosColumn(
          text: 'Sub-total:',
          width: 9,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
      PosColumn(
          text: formatPointNumber(
              (printTransactionModel.purchaseTransactionModel?.totalAmount ?? 0) +
                  (printTransactionModel.purchaseTransactionModel?.discountAmount ?? 0),
              addComma: true),
          width: 3,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
    ]);
    bytes += generator.row([
      PosColumn(
          text: 'Discount:',
          width: 9,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
      PosColumn(
        text: formatPointNumber(
            (printTransactionModel.purchaseTransactionModel?.discountAmount ?? 0),
            addComma: true),
        width: 3,
        styles: const PosStyles(
          align: PosAlign.right,
        ),
      ),
    ]);

    bytes += generator.row([
      PosColumn(
          text: 'Total Return Amount:',
          width: 9,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
      PosColumn(
          text: (formatPointNumber(
              printTransactionModel.purchaseTransactionModel?.totalAmount ?? 0,
              addComma: true)),
          width: 3,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
    ]);

    bytes += generator.text('                    ----------------------------');

    // bytes += generator.row([
    //   PosColumn(text: 'Total Payable:', width: 9, styles: const PosStyles(align: PosAlign.right, bold: true)),
    //   PosColumn(
    //       text: formatPointNumber(printTransactionModel.purchaseTransactionModel?.totalAmount ?? 0, addComma: true),
    //       width: 3,
    //       styles: const PosStyles(align: PosAlign.right, bold: true)),
    // ]);
    // bytes += generator.row([
    //   PosColumn(
    //       text: 'Paid Amount:',
    //       width: 9,
    //       styles: const PosStyles(
    //         align: PosAlign.right,
    //       )),
    //   PosColumn(
    //       text: formatPointNumber(printTransactionModel.purchaseTransactionModel!.totalAmount!.toDouble() - printTransactionModel.purchaseTransactionModel!.dueAmount!.toDouble(),
    //           addComma: true),
    //       width: 3,
    //       styles: const PosStyles(
    //         align: PosAlign.right,
    //       )),
    // ]);
    // if ((printTransactionModel.purchaseTransactionModel?.dueAmount ?? 0) > 0) {
    //   bytes += generator.row([
    //     PosColumn(
    //       text: 'Due Amount:',
    //       width: 9,
    //       styles: const PosStyles(
    //         align: PosAlign.right,
    //       ),
    //     ),
    //     PosColumn(
    //         text: formatPointNumber(printTransactionModel.purchaseTransactionModel?.dueAmount ?? 0, addComma: true),
    //         width: 3,
    //         styles: const PosStyles(
    //           align: PosAlign.right,
    //         )),
    //   ]);
    // } else {
    //   if (printTransactionModel.purchaseTransactionModel?.customerType != 'Guest') {
    //     bytes += generator.row([
    //       PosColumn(
    //         text: 'Change Amount:',
    //         width: 9,
    //         styles: const PosStyles(
    //           align: PosAlign.right,
    //         ),
    //       ),
    //       PosColumn(
    //           text: formatNumberForDecimal(printTransactionModel.purchaseTransactionModel!.returnAmount).toString(),
    //           width: 3,
    //           styles: const PosStyles(
    //             align: PosAlign.right,
    //           )),
    //     ]);
    //   }
    // }
    bytes += generator.hr();

    // bytes += generator.text(
    //   'Payment Type: ${printTransactionModel.purchaseTransactionModel?.paymentType ?? 'N/A'}',
    //   linesAfter: 1,
    // );

    bytes += generator.text('Thank you!',
        styles: const PosStyles(align: PosAlign.center, bold: true), linesAfter: 1);

    bytes += generator.text('Note: Goods once sold will not be taken back or exchanged.',
        styles: const PosStyles(align: PosAlign.center, bold: false), linesAfter: 1);
    bytes += generator.qrcode(pdfFooter, size: QRSize.size4);
    bytes += generator.text('Developed By: $invoiceName',
        styles: const PosStyles(align: PosAlign.center), linesAfter: 1);
    bytes += generator.cut();

    return bytes;
  }
}
