import 'package:esc_pos_utils_plus/esc_pos_utils_plus.dart';

import '../../../common/extension/extension.dart';
import '../../../domain/order/order.dart';
import '../../../domain/outlet/outlet.dart';
import 'receipt_component_builder.dart';

class PrintUi {
  Future<List<int>> printOrder({
    required Order order,
    required Outlet outlet,
    required String cashierName,
    int paper = 58,
  }) async {
    List<int> bytes = [];

    final profile = await CapabilityProfile.load();
    final generator = Generator(
      paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
      profile,
    );
    final builder = ReceiptComponentBuilder(
      generator: generator,
      paperSize: paper,
    );

    bytes += generator.reset();

    bytes += builder.header(
      outletName: outlet.name,
      address: outlet.address,
      phoneNumber: outlet.phoneNumber,
      fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.orderInfo(
      orderNumber: order.orderNumber,
      customerName: order.metadata['customer_name'] ?? '-',
      cashierName: cashierName,
      paymentMethod: order.payments.last.paymentMethodName,
      tableNumber: order.tableNumber,
      fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.orderType(order.orderType,   fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,);

    bytes += builder.emptyLines(1);

    for (final item in order.orderItemNotCancelled) {
      bytes += builder.orderItem(
        productName: item.productName,
        quantity: item.quantity,
        unitPrice: item.unitPrice.currencyFormatRpV2,
        totalPrice: item.totalPrice.currencyFormatRpV2,
        variantName: item.productVariantName,
        notes: item.notes,
         fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
      );
    }

    bytes += builder.summary(
      totalItems: order.orderItems.length,
      subtotal: order.subtotal.currencyFormatRpV2,
      discount: order.discountAmount.currencyFormatRpV2,
      total: order.totalAmount.currencyFormatRpV2,
      paid: order.totalPaid.currencyFormatRpV2,
      fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.footer();

    return bytes;
  }

  Future<List<int>> printChecker({
    required Order order,
    required Outlet outlet,
    required String cashierName,
    int paper = 58,
  }) async {
    List<int> bytes = [];

    final profile = await CapabilityProfile.load();
    final generator = Generator(
      paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
      profile,
    );
    final builder = ReceiptComponentBuilder(
      generator: generator,
      paperSize: paper,
    );

    bytes += generator.reset();

    // Header
    bytes += builder.textCenter('Table Checker', bold: true);
    bytes += builder.tableName(order.tableNumber.isNotEmpty ? order.tableNumber : '-', height: PosTextSize.size3, width: PosTextSize.size3);

    // Order info — label : value, left aligned
    bytes += builder.orderInfoSimple(
      orderNumber: order.orderNumber,
      orderType: order.orderType,
      cashierName: cashierName,
      customerName: order.metadata['customer_name'] ?? '-',
    );

    bytes += builder.separator();

    // Items — qty NAMA (uppercase), variant indent
    for (final item in order.orderItems.where((e) => e.printToChecker)) {
      final name = item.productName.toUpperCase();
      bytes += builder.itemText('${item.quantity} $name');
      if (item.productVariantName.isNotEmpty) {
        bytes += builder.itemText('  ${item.productVariantName.toUpperCase()}', bold: false);
      }
      if (item.notes.isNotEmpty) {
        bytes += builder.itemText('  *${item.notes}', bold: false);
      }
    }

    bytes += builder.separator();
    bytes += builder.cutOnly();

    return bytes;
  }

  Future<List<int>> printKitchen({
    required Order order,
    required Outlet outlet,
    required String cashierName,
    int paper = 58,
  }) async {
    List<int> bytes = [];

    final profile = await CapabilityProfile.load();
    final generator = Generator(
      paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
      profile,
    );
    final builder = ReceiptComponentBuilder(
      generator: generator,
      paperSize: paper,
    );

    for (final item in order.orderItems) {
      bytes += generator.reset();

      // Header
      bytes += builder.row2Columns('Kitchen', order.orderType.toUpperCase(), bold: true);
      bytes += builder.separator();
      bytes += builder.textCenter(
        'Table : ${order.tableNumber.isNotEmpty ? order.tableNumber : '-'}',
        bold: true,
      );
      bytes += builder.separator();

      // Order info
      bytes += builder.orderInfoSimple(
        orderNumber: order.orderNumber,
        cashierName: cashierName,
        customerName: order.metadata['customer_name'] ?? '-',
      );

      bytes += builder.separator();

      // Single item
      final name = item.productName.toUpperCase();
      bytes += builder.itemText('${item.quantity} $name');
      if (item.productVariantName.isNotEmpty) {
        bytes += builder.itemText('  ${item.productVariantName.toUpperCase()}', bold: false);
      }
      if (item.notes.isNotEmpty) {
        bytes += builder.itemText('  *${item.notes}', bold: false);
      }

      bytes += builder.separator();
      bytes += builder.cutOnly();
    }

    return bytes;
  }

  Future<List<int>> printBar({
    required Order order,
    required Outlet outlet,
    required String cashierName,
    int paper = 58,
  }) async {
    List<int> bytes = [];

    final profile = await CapabilityProfile.load();
    final generator = Generator(
      paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
      profile,
    );
    final builder = ReceiptComponentBuilder(
      generator: generator,
      paperSize: paper,
    );

    for (final item in order.orderItems) {
      bytes += generator.reset();

      // Header
      bytes += builder.row2Columns('Bar', order.orderType.toUpperCase(), bold: true);
      bytes += builder.separator();
      bytes += builder.textCenter(
        'Table : ${order.tableNumber.isNotEmpty ? order.tableNumber : '-'}',
        bold: true,
      );
      bytes += builder.separator();

      // Order info
      bytes += builder.orderInfoSimple(
        orderNumber: order.orderNumber,
        customerName: order.metadata['customer_name'] ?? '-',
        cashierName: cashierName,
      );

      bytes += builder.separator();

      // Single item
      final name = item.productName.toUpperCase();
      bytes += builder.itemText('${item.quantity} $name');
      if (item.productVariantName.isNotEmpty) {
        bytes += builder.itemText('  ${item.productVariantName.toUpperCase()}', bold: false);
      }
      if (item.notes.isNotEmpty) {
        bytes += builder.itemText('  *${item.notes}', bold: false);
      }

      bytes += builder.separator();
      bytes += builder.cutOnly();
    }

    return bytes;
  }

  Future<List<int>> printTicket({
    required Order order,
    required Outlet outlet,
    int paper = 58,
  }) async {
    List<int> bytes = [];

    final profile = await CapabilityProfile.load();
    final generator = Generator(
      paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
      profile,
    );
    final builder = ReceiptComponentBuilder(
      generator: generator,
      paperSize: paper,
    );

    bytes += generator.reset();

    bytes += builder.header(
      outletName: outlet.name,
      address: outlet.address,
      phoneNumber: outlet.phoneNumber,
    );

    bytes += builder.dateTime(DateTime.now());
    bytes += builder.row2Columns('Code No.', order.orderNumber);
    bytes += builder.separator();

    bytes += builder.emptyLines(2);
    bytes += builder.qrCode('1267128127182182');
    bytes += builder.emptyLines(1);
    bytes += builder.textCenter('1267128127182182');
    bytes += builder.emptyLines(2);

    bytes += builder.footer();

    return bytes;
  }

  Future<List<int>> printCashier({
    required Order order,
    required Outlet outlet,
    required String cashierName,
    int paper = 58,
  }) async {
    List<int> bytes = [];

    final profile = await CapabilityProfile.load();
    final generator = Generator(
      paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
      profile,
    );
    final builder = ReceiptComponentBuilder(
      generator: generator,
      paperSize: paper,
    );

    bytes += generator.reset();

    bytes += builder.header(
      outletName: outlet.name,
      address: outlet.address,
      phoneNumber: outlet.phoneNumber,
        fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.orderInfo(
      orderNumber: order.orderNumber,
      customerName: order.metadata['customer_name'] ?? '-',
      cashierName: cashierName,
      paymentMethod: order.payments.isEmpty
          ? null
          : order.payments.last.paymentMethodName,
      tableNumber: order.tableNumber,
        fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.orderType(order.orderType,   fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,);

    bytes += builder.emptyLines(1);

    for (final item in order.orderItemNotCancelled) {
      bytes += builder.orderItem(
        productName: item.productName,
        quantity: item.quantity,
        unitPrice: item.unitPrice.currencyFormatRpV2,
        totalPrice: item.totalPrice.currencyFormatRpV2,
        variantName: item.productVariantName,
        notes: item.notes,
          fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
      );
    }

    bytes += builder.summary(
      totalItems: order.orderItems.length,
      subtotal: order.subtotal.currencyFormatRpV2,
      discount: order.discountAmount.currencyFormatRpV2,
      total: order.totalAmount.currencyFormatRpV2,
      paid: order.totalPaid.currencyFormatRpV2,
      fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.footer(message: 'Kasir');

    return bytes;
  }

  Future<List<int>> printVoid({
    required Order order,
    required Outlet outlet,
    required String cashierName,
    int paper = 58,
  }) async {
    List<int> bytes = [];

    final profile = await CapabilityProfile.load();
    final generator = Generator(
      paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
      profile,
    );
    final builder = ReceiptComponentBuilder(
      generator: generator,
      paperSize: paper,
    );

    bytes += generator.reset();

    bytes += builder.header(
      outletName: outlet.name,
      address: outlet.address,
      phoneNumber: outlet.phoneNumber,
      fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.dateTime(DateTime.now());

    bytes += builder.orderInfo(
      orderNumber: order.orderNumber,
      customerName: order.metadata['customer_name'] ?? '-',
      cashierName: cashierName,
      paymentMethod: order.payments.isEmpty
          ? null
          : order.payments.last.paymentMethodName,
      tableNumber: order.tableNumber,
        fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.orderType('Void',   fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,);

    bytes += builder.emptyLines(1);

    for (final item in order.orderItems) {
      bytes += builder.orderItem(
        productName: item.productName,
        quantity: item.quantity,
        unitPrice: item.unitPrice.currencyFormatRpV2,
        totalPrice: item.totalPrice.currencyFormatRpV2,
        variantName: item.productVariantName,
        notes: item.notes,
          fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
      );
    }
    bytes += builder.summary(
      totalItems: order.orderItems.length,
      subtotal: order.subtotal.currencyFormatRpV2,
      discount: order.discountAmount.currencyFormatRpV2,
      total: order.totalAmount.currencyFormatRpV2,
      paid: order.totalPaid.currencyFormatRpV2,
      fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.footer(message: 'Kasir');

    return bytes;
  }

  Future<List<int>> printSplit({
    required Order order,
    required Outlet outlet,
    required String cashierName,
    int paper = 58,
  }) async {
    List<int> bytes = [];

    final profile = await CapabilityProfile.load();
    final generator = Generator(
      paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
      profile,
    );
    final builder = ReceiptComponentBuilder(
      generator: generator,
      paperSize: paper,
    );

    bytes += generator.reset();

    bytes += builder.header(
      outletName: outlet.name,
      address: outlet.address,
      phoneNumber: outlet.phoneNumber,
        fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.dateTime(DateTime.now(),   fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,);

    bytes += builder.orderInfo(
      orderNumber: order.orderNumber,
      customerName: order.metadata['customer_name'] ?? '-',
      cashierName: cashierName,
      paymentMethod: order.payments.isEmpty
          ? null
          : order.payments.last.paymentMethodName,
      tableNumber: order.tableNumber,
        fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.orderType('Split',   fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,);

    bytes += builder.row2Columns(
      'Split',
      '${order.payments.last.splitNumber} / ${order.payments.last.splitTotal}',
        fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.separator();

    bytes += builder.emptyLines(1);

    for (final item in order.orderItems) {
      bytes += builder.orderItem(
        productName: item.productName,
        quantity: item.quantity,
        unitPrice: item.unitPrice.currencyFormatRpV2,
        totalPrice: item.totalPrice.currencyFormatRpV2,
        variantName: item.productVariantName,
        notes: item.notes,
          fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
      );
    }

    bytes += builder.emptyLines(1);

    bytes += builder.summary(
      totalItems: 0,
      subtotal: order.payments.last.amount.currencyFormatRpV2,
      discount: 0.currencyFormatRpV2,
      total: order.payments.last.amount.currencyFormatRpV2,
      paid: order.payments.last.amount.currencyFormatRpV2,
        fontType: PosFontType.fontA,
      width: PosTextSize.size1,
      height: PosTextSize.size1,
    );

    bytes += builder.footer(message: 'Terima Kasih');

    return bytes;
  }
}
