import 'package:esc_pos_utils_plus/esc_pos_utils_plus.dart';
import 'package:flutter/services.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:print_bluetooth_thermal/print_bluetooth_thermal.dart';

import '../Provider/network_image.dart';
import '../constant.dart';
import '../model/print_transaction_model.dart';

class DueInvoiceThermal {
  Future<void> printDueTicket({required PrintDueTransactionModel printDueTransactionModel}) async {
    bool? isConnected = await PrintBluetoothThermal.connectionStatus;
    if (isConnected == true) {
      List<int> bytes = (printDueTransactionModel
                      .personalInformationModel.thermalPrinterPrintSize ==
                  '3 Inch (80 mm)' &&
              printDueTransactionModel.personalInformationModel.thermalPrinterPrintSize != null)
          ? await getDue80mmTicket(printDueTransactionModel: printDueTransactionModel)
          : await getDue58mmTicket(printDueTransactionModel: printDueTransactionModel);
      await PrintBluetoothThermal.writeBytes(bytes);
    } else {}
  }

  Future<List<int>> getDue58mmTicket(
      {required PrintDueTransactionModel printDueTransactionModel}) 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(printDueTransactionModel.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(printDueTransactionModel.personalInformationModel.companyName ?? '',
        styles: const PosStyles(
          align: PosAlign.center,
          height: PosTextSize.size2,
          width: PosTextSize.size2,
        ),
        linesAfter: 1);

    bytes += generator.text(printDueTransactionModel.personalInformationModel.countryName ?? '',
        styles: const PosStyles(align: PosAlign.center));
    bytes += generator.text(
        'Tel: ${printDueTransactionModel.personalInformationModel.phoneNumber ?? ''}',
        styles: const PosStyles(align: PosAlign.center),
        linesAfter:
            printDueTransactionModel.personalInformationModel.gst.trim().isNotEmpty ? 0 : 1);
    printDueTransactionModel.personalInformationModel.gst.trim().isNotEmpty
        ? bytes += generator.text(
            'Shop ${printDueTransactionModel.personalInformationModel.gstOrTinNameType == "" ? 'GST' : printDueTransactionModel.personalInformationModel.gstOrTinNameType}: ${printDueTransactionModel.personalInformationModel.gst ?? ''}',
            styles: const PosStyles(align: PosAlign.center),
            linesAfter: 1)
        : null;
    bytes += generator.text(
        'Received From: ${printDueTransactionModel.dueTransactionModel!.customerName} ',
        styles: const PosStyles(align: PosAlign.left));
    bytes += generator.text(
        'Mobile: ${printDueTransactionModel.dueTransactionModel!.customerPhone}',
        styles: const PosStyles(align: PosAlign.left));
    (printDueTransactionModel.dueTransactionModel?.customerGst.trim().isNotEmpty ?? false)
        ? bytes += generator.text(
            'Party ${printDueTransactionModel.personalInformationModel.gstOrTinNameType == "" ? 'GST' : printDueTransactionModel.personalInformationModel.gstOrTinNameType}: ${printDueTransactionModel.dueTransactionModel?.customerGst ?? 'Not Provided'}',
            styles: const PosStyles(align: PosAlign.left))
        : null;
    bytes += generator.text(
        'Receipt: ${printDueTransactionModel.dueTransactionModel?.invoiceNumber ?? 'N/A'}',
        styles: const PosStyles(align: PosAlign.left));
    bytes += generator.text(
      'Date: ${DateFormat.yMd().format(DateTime.parse(printDueTransactionModel.dueTransactionModel?.purchaseDate ?? DateTime.now().toString()))} ${DateFormat.jm().format(DateTime.parse(printDueTransactionModel.dueTransactionModel?.purchaseDate ?? DateTime.now().toString()))}',
      styles: const PosStyles(align: PosAlign.left),
    );
    bytes += generator.hr();
    bytes += generator.row([
      PosColumn(
          text: 'Invoice', width: 8, styles: const PosStyles(align: PosAlign.left, bold: true)),
      PosColumn(
          text: 'Due', width: 4, styles: const PosStyles(align: PosAlign.center, bold: true)),
    ]);
    bytes += generator.hr();
    bytes += generator.row([
      PosColumn(
          text: printDueTransactionModel.dueTransactionModel!.invoiceNumber,
          width: 8,
          styles: const PosStyles(
            align: PosAlign.left,
          )),
      PosColumn(
          text: printDueTransactionModel.dueTransactionModel!.totalDue.toString(),
          width: 4,
          styles: const PosStyles(
            align: PosAlign.center,
          )),
    ]);

    bytes += generator.hr();

    bytes += generator.row([
      PosColumn(
          text: 'Payment Type:',
          width: 8,
          styles: const PosStyles(
            align: PosAlign.left,
          )),
      PosColumn(
          text: printDueTransactionModel.dueTransactionModel!.paymentType.toString(),
          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: printDueTransactionModel.dueTransactionModel!.payDueAmount.toString(),
          width: 4,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
    ]);
    bytes += generator.row([
      PosColumn(
          text: 'Remaining Due:',
          width: 8,
          styles: const PosStyles(
            align: PosAlign.left,
          )),
      PosColumn(
          text: printDueTransactionModel.dueTransactionModel!.dueAmountAfterPay.toString(),
          width: 4,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
    ]);
    bytes += generator.hr(ch: '=', linesAfter: 1);

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

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

    // bytes += generator.qrcode('https://posbharat.com', size: QRSize.Size4);
    bytes += generator.text('Developed By: $invoiceName',
        styles: const PosStyles(align: PosAlign.center), linesAfter: 1);
    bytes += generator.cut();
    return bytes;
  }

  Future<List<int>> getDue80mmTicket(
      {required PrintDueTransactionModel printDueTransactionModel}) async {
    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(
          printDueTransactionModel.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(printDueTransactionModel.personalInformationModel.companyName ?? '',
        styles: const PosStyles(
          align: PosAlign.center,
          height: PosTextSize.size2,
          width: PosTextSize.size2,
        ),
        linesAfter: 1);
    if (printDueTransactionModel.personalInformationModel.countryName != null) {
      bytes += generator.text(
          'Address: ${printDueTransactionModel.personalInformationModel.countryName}',
          styles: const PosStyles(align: PosAlign.center));
    }
    if (printDueTransactionModel.personalInformationModel.phoneNumber != null) {
      bytes += generator.text(
          'Mobile: ${printDueTransactionModel.personalInformationModel.phoneNumber}',
          styles: const PosStyles(align: PosAlign.center));
    }
    bytes += generator.emptyLines(1);
    bytes += generator.text('RECEIPT',
        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:
              'Due Invoice: ${printDueTransactionModel.dueTransactionModel?.invoiceNumber ?? 'Not Provided'}',
          width: 6,
          styles: const PosStyles(align: PosAlign.left)),
      PosColumn(
          text:
              'Date: ${DateFormat.yMd().format(DateTime.parse(printDueTransactionModel.dueTransactionModel?.purchaseDate ?? DateTime.now().toString()))}',
          width: 6,
          styles: const PosStyles(align: PosAlign.right)),
    ]);
    bytes += generator.row([
      PosColumn(
          text:
              'Received From: ${printDueTransactionModel.dueTransactionModel?.customerName ?? ''}',
          width: 6,
          styles: const PosStyles(align: PosAlign.left)),
      PosColumn(
          text:
              'Time: ${DateFormat.jm().format(DateTime.parse(printDueTransactionModel.dueTransactionModel?.purchaseDate ?? DateTime.now().toString()))}',
          width: 6,
          styles: const PosStyles(align: PosAlign.right)),
    ]);
    bytes += generator.row([
      PosColumn(
          text: 'Mobile: ${printDueTransactionModel.dueTransactionModel?.customerPhone ?? ''}',
          width: 6,
          styles: const PosStyles(align: PosAlign.left)),
      PosColumn(
          text: 'Collected By: ${'Admin'}',
          width: 6,
          styles: const PosStyles(align: PosAlign.right)),
    ]);

    bytes += generator.emptyLines(1);

    ///____________Products_Section_____________________________________________________
    bytes += generator.hr();
    bytes += generator.row([
      PosColumn(
          text: 'Invoice', width: 8, styles: const PosStyles(align: PosAlign.left, bold: true)),
      PosColumn(
          text: 'Due', width: 4, styles: const PosStyles(align: PosAlign.center, bold: true)),
    ]);
    bytes += generator.hr();
    bytes += generator.row([
      PosColumn(
          text: printDueTransactionModel.dueTransactionModel!.invoiceNumber,
          width: 8,
          styles: const PosStyles(
            align: PosAlign.left,
          )),
      PosColumn(
          text: printDueTransactionModel.dueTransactionModel!.totalDue.toString(),
          width: 4,
          styles: const PosStyles(
            align: PosAlign.center,
          )),
    ]);
    bytes += generator.hr();

    bytes += generator.row([
      PosColumn(
          text: 'Payment Amount:',
          width: 9,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
      PosColumn(
          text: printDueTransactionModel.dueTransactionModel!.payDueAmount.toString(),
          width: 3,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
    ]);
    bytes += generator.row([
      PosColumn(
          text: 'Remaining Due:',
          width: 9,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
      PosColumn(
          text: printDueTransactionModel.dueTransactionModel!.dueAmountAfterPay.toString(),
          width: 3,
          styles: const PosStyles(
            align: PosAlign.right,
          )),
    ]);

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

    bytes += generator.text(
      'Payment Type: ${printDueTransactionModel.dueTransactionModel?.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;
  }
}
