import 'dart:developer';
import 'dart:typed_data';

import 'package:barcode_image/barcode_image.dart';
import 'package:enaklo_pos/core/extensions/string_ext.dart';
import 'package:enaklo_pos/core/utils/printer_service.dart';
import 'package:enaklo_pos/data/dataoutputs/print_dataoutputs.dart';
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
import 'package:enaklo_pos/data/datasources/outlet/outlet_local_datasource.dart';
import 'package:enaklo_pos/data/datasources/printer/printer_local_datasource.dart';
import 'package:enaklo_pos/data/datasources/settings_local_datasource.dart';
import 'package:enaklo_pos/data/models/response/order_response_model.dart';
import 'package:enaklo_pos/data/type/bussines_type.dart';
import 'package:enaklo_pos/presentation/home/models/product_quantity.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';
import 'package:barcode/barcode.dart';
import 'package:image/image.dart' as img;

Future<void> onPrint(
  BuildContext context, {
  required List<ProductQuantity> productQuantity,
  required Order order,
}) async {
  final outlet = await OutletLocalDatasource().get();
  final settings = await SettingsLocalDatasource().getTax();
  final authData = await AuthLocalDataSource().getAuthData();

  if (outlet.businessType == BusinessType.restaurant) {
    final checkerPrinter =
        await PrinterLocalDatasource.instance.getPrinterByCode('checker');
    final kitchenPrinter =
        await PrinterLocalDatasource.instance.getPrinterByCode('kitchen');
    final barPrinter =
        await PrinterLocalDatasource.instance.getPrinterByCode('bar');
    final receiptPrinter =
        await PrinterLocalDatasource.instance.getPrinterByCode('receipt');

    if (receiptPrinter != null) {
      try {
        final printValue = await PrintDataoutputs.instance.printOrderV4(
            order,
            authData.user?.name ?? "",
            '',
            0,
            0,
            settings.value,
            receiptPrinter.paper.toIntegerFromText,
            order.orderType ?? "",
            outlet,
            productQuantity);
        await PrinterService()
            .printWithPrinter(receiptPrinter, printValue, context);
      } catch (e, stackTrace) {
        FirebaseCrashlytics.instance.recordError(
          e,
          stackTrace,
          reason: 'Print receipt failed',
          information: [
            'Order ID: ${order.id}',
            'Printer: ${receiptPrinter.name}',
          ],
        );
        log("Error printing receipt order: $e");
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error printing receipt order: $e')),
        );
      }
    } else {
      FirebaseCrashlytics.instance.recordError(
        'Receipt printer not found',
        null,
        reason:
            'Receipt printer not found / Printer not setting in printer page',
        information: [
          'Order ID: ${order.id}',
        ],
      );
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Anda belum menghubungkan printer receipt')),
      );
    }

    // Checker printer
    if (checkerPrinter != null) {
      try {
        final printValue = await PrintDataoutputs.instance.printChecker(
          productQuantity,
          order.tableNumber ?? "",
          order.orderNumber ?? "",
          authData.user?.name ?? "",
          order.metadata?['customer_name'] ?? "",
          checkerPrinter.paper.toIntegerFromText,
          order.orderType ?? "",
        );

        if (productQuantity.isNotEmpty) {
          await PrinterService()
              // ignore: use_build_context_synchronously
              .printWithPrinter(checkerPrinter, printValue, context);
        }
      } catch (e, stackTrace) {
        log("Error printing checker: $e");
        FirebaseCrashlytics.instance.recordError(
          e,
          stackTrace,
          reason: 'Error printing checker ${checkerPrinter.name}',
          information: [
            'Printer: checker',
            'data: ${checkerPrinter.toMap()}',
          ],
        );
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error printing checker: $e')),
        );
      }
    } else {
      FirebaseCrashlytics.instance.recordError(
        'Checker printer not found',
        null,
        reason:
            'Checker printer not found / Printer not setting in printer page',
        information: [
          'Order ID: ${order.id}',
        ],
      );
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Anda belum menghubungkan printer checker')),
      );
    }

    // Kitchen printer
    if (kitchenPrinter != null) {
      try {
        final productByPrinter = productQuantity
            .where((item) => item.product.printerType == 'kitchen')
            .toList();
        final printValue =
            await PrintDataoutputs.instance.printKitchenPerProduct(
          productByPrinter,
          order.tableNumber ?? "",
          order.orderNumber ?? "",
          authData.user?.name ?? "",
          order.metadata?['customer_name'] ?? "",
          kitchenPrinter.paper.toIntegerFromText,
          order.orderType ?? "",
        );

        if (productByPrinter.isNotEmpty) {
          await PrinterService()
              .printWithPrinter(kitchenPrinter, printValue, context);
        }
      } catch (e, stackTrace) {
        log("Error printing kitchen order: $e");
        FirebaseCrashlytics.instance.recordError(
          e,
          stackTrace,
          reason: 'Error printing kitchen ${kitchenPrinter.name}',
          information: [
            'Printer: kitchen',
            'data: ${kitchenPrinter.toMap()}',
          ],
        );
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error printing kitchen order: $e')),
        );
      }
    } else {
      FirebaseCrashlytics.instance.recordError(
        'Kitchen printer not found',
        null,
        reason:
            'Kitchen printer not found / Printer not setting in printer page',
        information: [
          'Order ID: ${order.id}',
        ],
      );
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Anda belum menghubungkan printer kitchen')),
      );
    }

    // Bar printer
    if (barPrinter != null) {
      try {
        final productByPrinter = productQuantity
            .where((item) => item.product.printerType == 'bar')
            .toList();

        final printValue = await PrintDataoutputs.instance.printBar(
          productByPrinter,
          order.tableNumber ?? "",
          order.orderNumber ?? "",
          authData.user?.name ?? "",
          order.metadata?['customer_name'] ?? "",
          barPrinter.paper.toIntegerFromText,
          order.orderType ?? "",
        );

        if (productByPrinter.isNotEmpty) {
          await PrinterService()
              .printWithPrinter(barPrinter, printValue, context);
        }
      } catch (e, stackTrace) {
        log("Error printing bar order: $e");
        FirebaseCrashlytics.instance.recordError(
          e,
          stackTrace,
          reason: 'Error printing bar ${barPrinter.name}',
          information: [
            'Printer: bar',
            'data: ${barPrinter.toMap()}',
          ],
        );
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error printing bar order: $e')),
        );
      }
    } else {
      FirebaseCrashlytics.instance.recordError(
        'Bar printer not found',
        null,
        reason: 'Bar printer not found / Printer not setting in printer page',
        information: [
          'Order ID: ${order.id}',
        ],
      );
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Anda belum menghubungkan printer bar')),
      );
    }
  }

  if (outlet.businessType == BusinessType.ticketing) {
    final ticketPrinter =
        await PrinterLocalDatasource.instance.getPrinterByCode('ticket');

    final barcode = await generateBarcodeAsUint8List(order.orderNumber ?? "");

    if (ticketPrinter != null) {
      try {
        final printValue = await PrintDataoutputs.instance.printTicket(
          order.totalAmount ?? 0,
          barcode,
          ticketPrinter.paper.toIntegerFromText,
        );

        await PrinterService()
            // ignore: use_build_context_synchronously
            .printWithPrinter(ticketPrinter, printValue, context);
      } catch (e, stackTrace) {
        FirebaseCrashlytics.instance.recordError(
          e,
          stackTrace,
          reason: 'Error printing ticket ${ticketPrinter.name}',
          information: [
            'Printer: ticket',
            'data: ${ticketPrinter.toMap()}',
          ],
        );
        log("Error printing ticket: $e");
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error printing ticket: $e')),
        );
      }
    } else {
      FirebaseCrashlytics.instance.recordError(
        'Ticket printer not found',
        null,
        reason:
            'Ticket printer not found / Printer not setting in printer page',
        information: [
          'Order ID: ${order.id}',
        ],
      );
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Anda belum menghubungkan printer ticket')),
      );
    }
  }
}

Future<void> onPrintBill(
  BuildContext context, {
  required List<ProductQuantity> productQuantity,
  required Order order,
}) async {
  final outlet = await OutletLocalDatasource().get();
  final settings = await SettingsLocalDatasource().getTax();
  final authData = await AuthLocalDataSource().getAuthData();

  if (outlet.businessType == BusinessType.restaurant) {
    final receiptPrinter =
        await PrinterLocalDatasource.instance.getPrinterByCode('receipt');

    if (receiptPrinter != null) {
      try {
        final printValue = await PrintDataoutputs.instance.printOrderV4(
            order,
            authData.user?.name ?? "",
            '',
            0,
            0,
            settings.value,
            receiptPrinter.paper.toIntegerFromText,
            order.orderType ?? "",
            outlet,
            productQuantity);
        await PrinterService()
            .printWithPrinter(receiptPrinter, printValue, context);
      } catch (e, stackTrace) {
        FirebaseCrashlytics.instance.recordError(
          e,
          stackTrace,
          reason: 'Print receipt failed',
          information: [
            'Order ID: ${order.id}',
            'Printer: ${receiptPrinter.name}',
          ],
        );
        log("Error printing receipt order: $e");
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error printing receipt order: $e')),
        );
      }
    } else {
      FirebaseCrashlytics.instance.recordError(
        'Receipt printer not found',
        null,
        reason:
            'Receipt printer not found / Printer not setting in printer page',
        information: [
          'Order ID: ${order.id}',
        ],
      );
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Anda belum menghubungkan printer receipt')),
      );
    }
  }

  if (outlet.businessType == BusinessType.ticketing) {
    final ticketPrinter =
        await PrinterLocalDatasource.instance.getPrinterByCode('ticket');

    final barcode = await generateBarcodeAsUint8List(order.orderNumber ?? "");

    if (ticketPrinter != null) {
      try {
        final printValue = await PrintDataoutputs.instance.printTicket(
          order.totalAmount ?? 0,
          barcode,
          ticketPrinter.paper.toIntegerFromText,
        );

        await PrinterService()
            // ignore: use_build_context_synchronously
            .printWithPrinter(ticketPrinter, printValue, context);
      } catch (e, stackTrace) {
        FirebaseCrashlytics.instance.recordError(
          e,
          stackTrace,
          reason: 'Error printing ticket ${ticketPrinter.name}',
          information: [
            'Printer: ticket',
            'data: ${ticketPrinter.toMap()}',
          ],
        );
        log("Error printing ticket: $e");
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error printing ticket: $e')),
        );
      }
    } else {
      FirebaseCrashlytics.instance.recordError(
        'Ticket printer not found',
        null,
        reason:
            'Ticket printer not found / Printer not setting in printer page',
        information: [
          'Order ID: ${order.id}',
        ],
      );
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Anda belum menghubungkan printer ticket')),
      );
    }
  }
}

Future<void> onPrintRecipt(
  context, {
  required Order order,
  required String paymentMethod,
  required int nominalBayar,
  required int kembalian,
  required List<ProductQuantity> productQuantity,
}) async {
  final receiptPrinter =
      await PrinterLocalDatasource.instance.getPrinterByCode('receipt');
  final authData = await AuthLocalDataSource().getAuthData();
  final settings = await SettingsLocalDatasource().getTax();
  final outlet = await OutletLocalDatasource().get();

  if (receiptPrinter != null) {
    try {
      final printValue = await PrintDataoutputs.instance.printOrderV4(
          order,
          authData.user?.name ?? "",
          paymentMethod,
          nominalBayar,
          kembalian,
          settings.value,
          receiptPrinter.paper.toIntegerFromText,
          order.orderType ?? "",
          outlet,
          productQuantity);
      await PrinterService()
          .printWithPrinter(receiptPrinter, printValue, context);
    } catch (e, stackTrace) {
      FirebaseCrashlytics.instance.recordError(
        e,
        stackTrace,
        reason: 'Print receipt failed',
        information: [
          'Order ID: ${order.id}',
          'Payment Method: $paymentMethod',
          'Printer: ${receiptPrinter.name}',
        ],
      );
      log("Error printing receipt order: $e");
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Error printing receipt order: $e')),
      );
    }
  } else {
    FirebaseCrashlytics.instance.recordError(
      'Kitchen printer not found',
      null,
      reason: 'Kitchen printer not found / Printer not setting in printer page',
      information: [
        'Order ID: ${order.id}',
      ],
    );
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Anda belum menghubungkan printer kitchen')),
    );
  }
}

Future<void> onPrinVoidRecipt(
  context, {
  required Order order,
  required List<OrderItem> productItemVoid,
  required int totalVoid,
}) async {
  final receiptPrinter =
      await PrinterLocalDatasource.instance.getPrinterByCode('receipt');
  final authData = await AuthLocalDataSource().getAuthData();
  final settings = await SettingsLocalDatasource().getTax();
  final outlet = await OutletLocalDatasource().get();

  if (receiptPrinter != null) {
    try {
      final printValue = await PrintDataoutputs.instance.printVoidOrder(
          order,
          authData.user?.name ?? "",
          settings.value,
          receiptPrinter.paper.toIntegerFromText,
          totalVoid,
          outlet,
          productItemVoid);
      await PrinterService()
          .printWithPrinter(receiptPrinter, printValue, context);
    } catch (e) {
      log("Error printing receipt order: $e");
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Error printing receipt order: $e')),
      );
    }
  }
}

Future<void> onPrintSplit(
  context, {
  required Order order,
}) async {
  final receiptPrinter =
      await PrinterLocalDatasource.instance.getPrinterByCode('receipt');
  final authData = await AuthLocalDataSource().getAuthData();
  final settings = await SettingsLocalDatasource().getTax();
  final outlet = await OutletLocalDatasource().get();

  if (receiptPrinter != null) {
    try {
      final printValue = await PrintDataoutputs.instance.printSplitBill(
        order,
        authData.user?.name ?? "",
        receiptPrinter.paper.toIntegerFromText,
        outlet,
      );
      await PrinterService()
          .printWithPrinter(receiptPrinter, printValue, context);
    } catch (e, stackTrace) {
      FirebaseCrashlytics.instance.recordError(
        e,
        stackTrace,
        reason: 'Print receipt failed',
        information: [
          'Order ID: ${order.id}',
          'Printer: ${receiptPrinter.name}',
        ],
      );
      log("Error printing receipt order: $e");
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Error printing receipt order: $e')),
      );
    }
  } else {
    FirebaseCrashlytics.instance.recordError(
      'Kitchen printer not found',
      null,
      reason: 'Kitchen printer not found / Printer not setting in printer page',
      information: [
        'Order ID: ${order.id}',
      ],
    );
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Anda belum menghubungkan printer kitchen')),
    );
  }
}

Future<Uint8List> generateBarcodeAsUint8List(String data) async {
  // 1. Buat barcode instance (code128, qrCode, dll)
  final barcode = Barcode.code128();

  // 2. Siapkan canvas image dari package `image`
  final image = img.Image(width: 600, height: 200);

  // 3. Gambar barcode ke canvas menggunakan barcode_image
  drawBarcode(
    image,
    barcode,
    data,
  );

  // 4. Encode image ke Uint8List PNG
  return Uint8List.fromList(img.encodePng(image));
}
