import 'package:esc_pos_utils_plus/esc_pos_utils_plus.dart';
import 'package:intl/intl.dart';

/// Reusable component builder untuk thermal receipt printer
class ReceiptComponentBuilder {
  final Generator generator;
  final int paperSize;

  ReceiptComponentBuilder({required this.generator, this.paperSize = 58});

  /// Get separator line based on paper size
  String get _separator => paperSize == 80
      ? '------------------------------------------------'
      : '--------------------------------';

  /// Print text centered with custom style
  List<int> textCenter(
    String text, {
    bool bold = false,
    PosTextSize height = PosTextSize.size1,
    PosTextSize width = PosTextSize.size1,
  }) {
    return generator.text(
      text,
      styles: PosStyles(
        bold: bold,
        align: PosAlign.center,
        height: height,
        width: width,
      ),
    );
  }

  /// Print text aligned left
  List<int> textLeft(String text, {bool bold = false}) {
    return generator.text(
      text,
      styles: PosStyles(bold: bold, align: PosAlign.left),
    );
  }

  /// Print text aligned right
  List<int> textRight(String text, {bool bold = false}) {
    return generator.text(
      text,
      styles: PosStyles(bold: bold, align: PosAlign.right),
    );
  }

  /// Print separator line
  List<int> separator({bool bold = false}) {
    return generator.text(
      _separator,
      styles: PosStyles(bold: bold, align: PosAlign.center),
    );
  }

  /// Print row with 2 columns (label: value)
  List<int> row2Columns(
    String leftText,
    String rightText, {
    bool bold = false,
    int leftWidth = 6,
    int rightWidth = 6,
  }) {
    return generator.row([
      PosColumn(
        text: leftText,
        width: leftWidth,
        styles: PosStyles(align: PosAlign.left, bold: bold),
      ),
      PosColumn(
        text: rightText,
        width: rightWidth,
        styles: PosStyles(align: PosAlign.right, bold: bold),
      ),
    ]);
  }

  /// Print row with 3 columns
  List<int> row3Columns(
    String leftText,
    String centerText,
    String rightText, {
    int leftWidth = 4,
    int centerWidth = 4,
    int rightWidth = 4,
  }) {
    return generator.row([
      PosColumn(
        text: leftText,
        width: leftWidth,
        styles: const PosStyles(align: PosAlign.left),
      ),
      PosColumn(
        text: centerText,
        width: centerWidth,
        styles: const PosStyles(align: PosAlign.center),
      ),
      PosColumn(
        text: rightText,
        width: rightWidth,
        styles: const PosStyles(align: PosAlign.right),
      ),
    ]);
  }

  /// Print empty lines
  List<int> emptyLines(int count) {
    return generator.emptyLines(count);
  }

  /// Print feed lines
  List<int> feed(int count) {
    return generator.feed(count);
  }

  /// Print header (outlet info)
  List<int> header({
    required String outletName,
    required String address,
    required String phoneNumber,
  }) {
    List<int> bytes = [];

    bytes += textCenter(
      outletName,
      bold: true,
      height: PosTextSize.size1,
      width: PosTextSize.size1,
    );
    bytes += textCenter(address);
    bytes += textCenter(phoneNumber);
    bytes += separator();

    return bytes;
  }

  List<int> printerType({required String printerType}) {
    List<int> bytes = [];

    bytes += textCenter(
      printerType,
      bold: true,
      height: PosTextSize.size1,
      width: PosTextSize.size1,
    );

    return bytes;
  }

  /// Print date and time
  List<int> dateTime(DateTime dateTime) {
    return row2Columns(
      DateFormat('dd MMM yyyy').format(dateTime),
      DateFormat('HH:mm').format(dateTime),
    );
  }

  /// Print order info section
  List<int> orderInfo({
    required String orderNumber,
    required String customerName,
    required String cashierName,
    String? paymentMethod,
    String? tableNumber,
  }) {
    List<int> bytes = [];

    bytes += row2Columns('No. Pesanan', orderNumber);
    bytes += row2Columns('Pelanggan', customerName);
    bytes += row2Columns('Kasir', cashierName);

    if (paymentMethod != null) {
      bytes += row2Columns(
        'Pembayaran',
        paymentMethod,
        leftWidth: 8,
        rightWidth: 4,
      );
    }

    if (tableNumber != null && tableNumber.isNotEmpty) {
      bytes += row2Columns('Meja', tableNumber, leftWidth: 8, rightWidth: 4);
    }

    return bytes;
  }

  /// Print order type (Dine In, Take Away, etc)
  List<int> orderType(String type) {
    List<int> bytes = [];

    bytes += separator();
    bytes += textCenter(type, bold: true);
    bytes += separator();

    return bytes;
  }

  /// Print single item
  List<int> orderItem({
    required String productName,
    required int quantity,
    required String unitPrice,
    required String totalPrice,
    String? variantName,
    String? notes,
  }) {
    List<int> bytes = [];

    final variantText = variantName != null && variantName.isNotEmpty
        ? "($variantName)"
        : '';

    bytes += textLeft('$productName $variantText', bold: true);
    bytes += row2Columns(
      '$quantity x $unitPrice',
      totalPrice,
      leftWidth: 8,
      rightWidth: 4,
    );

    if (notes != null && notes.isNotEmpty) {
      bytes += row2Columns('Note', notes, leftWidth: 4, rightWidth: 8);
    }

    bytes += emptyLines(1);

    return bytes;
  }

  /// Print summary section
  List<int> summary({
    required int totalItems,
    required String subtotal,
    required String discount,
    required String total,
    required String paid,
  }) {
    List<int> bytes = [];

    bytes += separator();
    if (totalItems > 0) {
      bytes += row2Columns('Total Item', totalItems.toString());
    }
    bytes += row2Columns('Subtotal', subtotal);
    bytes += row2Columns('Diskon', discount);
    bytes += separator();
    bytes += row2Columns('Total', total, bold: true);
    bytes += row2Columns('Bayar', paid);
    bytes += separator();

    return bytes;
  }

  /// Print footer (thank you message)
  List<int> footer({String message = 'Terima kasih'}) {
    List<int> bytes = [];

    bytes += emptyLines(2);
    bytes += textCenter(
      message,
      bold: true,
      height: PosTextSize.size1,
      width: PosTextSize.size1,
    );
    bytes += feed(paperSize == 80 ? 3 : 1);
    bytes += generator.cut();

    return bytes;
  }

  /// Print QR Code
  List<int> qrCode(String data, {PosAlign align = PosAlign.center}) {
    return generator.qrcode(data, align: align);
  }

  /// Print barcode
  List<int> barcode(String data) {
    return generator.barcode(Barcode.code128(data.codeUnits));
  }
}
