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_local_datasource.dart';
import 'package:enaklo_pos/data/datasources/product_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: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();
  if (outlet.businessType == BusinessType.restaurant) {
    final checkerPrinter =
        await ProductLocalDatasource.instance.getPrinterByCode('checker');
    final kitchenPrinter =
        await ProductLocalDatasource.instance.getPrinterByCode('kitchen');
    final barPrinter =
        await ProductLocalDatasource.instance.getPrinterByCode('bar');

    final authData = await AuthLocalDataSource().getAuthData();

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

        await PrinterService()
            // ignore: use_build_context_synchronously
            .printWithPrinter(checkerPrinter, printValue, context);
      } catch (e) {
        log("Error printing checker: $e");
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error printing checker: $e')),
        );
      }
    }

    // Kitchen printer
    if (kitchenPrinter != null) {
      try {
        final printValue = await PrintDataoutputs.instance.printKitchen(
          productQuantity,
          order.tableNumber!,
          order.orderNumber ?? "",
          authData.user?.name ?? "",
          kitchenPrinter.paper.toIntegerFromText,
          order.orderType ?? "",
        );

        await PrinterService()
            .printWithPrinter(kitchenPrinter, printValue, context);
      } catch (e) {
        log("Error printing kitchen order: $e");
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error printing kitchen order: $e')),
        );
      }
    }

    // Bar printer
    if (barPrinter != null) {
      try {
        final printValue = await PrintDataoutputs.instance.printBar(
          productQuantity,
          order.tableNumber ?? "",
          order.orderNumber ?? "",
          authData.user?.name ?? "",
          barPrinter.paper.toIntegerFromText,
          order.orderType ?? "",
        );

        await PrinterService()
            .printWithPrinter(barPrinter, printValue, context);
      } catch (e) {
        log("Error printing bar order: $e");
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error printing bar order: $e')),
        );
      }
    }
  }

  if (outlet.businessType == BusinessType.ticketing) {
    final ticketPrinter =
        await ProductLocalDatasource.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) {
        log("Error printing ticket: $e");
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error printing ticket: $e')),
        );
      }
    }
  }
}

Future<void> onPrintRecipt(
  context, {
  required Order order,
  required String paymentMethod,
  required int nominalBayar,
  required int kembalian,
}) async {
  final receiptPrinter =
      await ProductLocalDatasource.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,
      );
      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<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));
}
