import 'package:esc_pos_utils_plus/esc_pos_utils_plus.dart';
import 'package:flutter/foundation.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});

  /// Helper: returns size2 for 80mm paper, size1 for 58mm
  PosTextSize get _titleSize =>
      paperSize == 80 ? PosTextSize.size3 : PosTextSize.size1;

  /// Font type per paper size — easy to change here
  /// 58mm → fontA, 80mm → fontA
  PosFontType get _font =>
      paperSize == 80 ? PosFontType.fontA : PosFontType.fontA;

  /// Text size for body — height size2 for 80mm to appear taller, size1 for 58mm
  PosTextSize get _bodySize =>
      paperSize == 80 ? PosTextSize.size2 : PosTextSize.size1;

  /// Body width stays size1 always to prevent overflow
  PosTextSize get _bodyWidth => PosTextSize.size1;

  /// Characters per line based on paper size (always size1 font)
  String get _separatorLine => paperSize == 80
      ? '------------------------------------------------'
      : '--------------------------------';

  // ---------------------------------------------------------------------------
  // Basic text
  // ---------------------------------------------------------------------------

  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,
        fontType: _font,
      ),
    );
  }

  List<int> textLeft(String text, {bool bold = false}) {
    return generator.text(
      text,
      styles: PosStyles(
        bold: bold,
        align: PosAlign.left,
        fontType: _font,
        height: _bodySize,
        width: _bodyWidth,
      ),
    );
  }

  List<int> textRight(String text, {bool bold = false}) {
    return generator.text(
      text,
      styles: PosStyles(
        bold: bold,
        align: PosAlign.right,
        fontType: _font,
        height: _bodySize,
        width: _bodyWidth,
      ),
    );
  }

  // ---------------------------------------------------------------------------
  // Layout helpers
  // ---------------------------------------------------------------------------

  List<int> separator({bool bold = false}) {
    return generator.text(
      _separatorLine,
      styles: PosStyles(
        bold: bold,
        align: PosAlign.center,
        height: PosTextSize.size1,
        width: PosTextSize.size1,
        fontType: _font,
      ),
    );
  }

  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,
          fontType: _font,
          height: _bodySize,
          width: _bodyWidth,
        ),
      ),
      PosColumn(
        text: rightText,
        width: rightWidth,
        styles: PosStyles(
          align: PosAlign.right,
          bold: bold,
          fontType: _font,
          height: _bodySize,
          width: _bodyWidth,
        ),
      ),
    ]);
  }

  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),
      ),
    ]);
  }

  /// Item text — always size2 for kitchen/checker (prominent display)
  List<int> itemText(String text, {bool bold = true}) {
    return generator.text(
      text,
      styles: PosStyles(
        bold: bold,
        align: PosAlign.left,
        fontType: _font,
        height: PosTextSize.size2,
        width: PosTextSize.size2,
      ),
    );
  }

  List<int> emptyLines(int count) => generator.emptyLines(count);

  List<int> feed(int count) => generator.feed(count);

  // ---------------------------------------------------------------------------
  // Composite components
  // ---------------------------------------------------------------------------

  /// Outlet header (receipt/cashier style)
  List<int> header({
    required String outletName,
    required String address,
    required String phoneNumber,
  }) {
    List<int> bytes = [];
    bytes += textCenter(outletName, bold: true, height: _titleSize, width: _titleSize);
    bytes += textCenter(address);
    bytes += textCenter(phoneNumber);
    bytes += separator();
    return bytes;
  }

  /// Centered printer type label (e.g. KITCHEN, BAR)
  List<int> printerType({required String printerType}) {
    return textCenter(printerType, bold: true, height: _titleSize, width: _titleSize);
  }

  /// Date + time row (receipt style)
  List<int> dateTime(DateTime dateTime) {
    return row2Columns(
      DateFormat('dd MMM yyyy').format(dateTime),
      DateFormat('HH:mm').format(dateTime),
    );
  }

  /// Order info block — label : value style (checker/kitchen style)
  List<int> orderInfoSimple({
    required String orderNumber,
    String? orderType,
    required String cashierName,
  }) {
    List<int> bytes = [];
    final dateStr = DateFormat('dd-MM-yyyy HH:mm').format(DateTime.now());
    bytes += textLeft('Order   : $orderNumber');
    bytes += textLeft('Date    : $dateStr');
    if(orderType != null) {
       bytes += textLeft('Purpose : $orderType');
    }
    bytes += textLeft('Waiter  : $cashierName');
    return bytes;
  }

  /// Order info block — row2Columns style (receipt/cashier style)
  List<int> orderInfo({
    required String orderNumber,
    required String customerName,
    required String cashierName,
    String? paymentMethod,
    String? tableNumber,
  }) {
    List<int> bytes = [];
     final dateStr = DateFormat('dd-MM-yyyy HH:mm').format(DateTime.now());
      bytes += textLeft('Order    : $orderNumber');
      bytes += textLeft('Date     : $dateStr');
       if (tableNumber != null && tableNumber.isNotEmpty) {
      bytes += textLeft('Table    : $tableNumber');
    }
      bytes += textLeft('Waiter   : $cashierName');
      bytes += textLeft('Customer : $customerName');
     
    if (paymentMethod != null) {
       bytes += textLeft('Payment  : $paymentMethod');
    }
   
    return bytes;
  }

  /// Order type banner (separator + type + separator)
  List<int> orderType(String type) {
    List<int> bytes = [];
    bytes += separator();
    bytes += textCenter(type, bold: true, height: _titleSize, width: _titleSize);
    bytes += separator();
    return bytes;
  }

  /// Single item row with price (receipt/cashier style)
  List<int> orderItem({
    required String productName,
    required int quantity,
    required String unitPrice,
    required String totalPrice,
    String? variantName,
    String? notes,
  }) {
    List<int> bytes = [];
    final displayName = (variantName != null && variantName.isNotEmpty)
        ? '$productName ($variantName)'
        : productName;
    bytes += textLeft(displayName, bold: paperSize == 80);
    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;
  }

  /// 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;
  }

  /// Footer with thank-you message + cut
  List<int> footer({String message = 'Terima kasih'}) {
    List<int> bytes = [];
    bytes += emptyLines(2);
    bytes += textCenter(message, bold: true, height: _titleSize, width: _titleSize);
    if (kDebugMode) {
      bytes += textCenter('$paperSize MM');
    }
    bytes += feed(paperSize == 80 ? 3 : 1);
    bytes += generator.cut();
    return bytes;
  }

  /// Feed + cut without any message
  List<int> cutOnly() {
    List<int> bytes = [];
    bytes += feed(paperSize == 80 ? 3 : 1);
    bytes += generator.cut();
    return bytes;
  }

  // ---------------------------------------------------------------------------
  // Media
  // ---------------------------------------------------------------------------

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

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