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

  PosFontType get _font =>
      paperSize == 80 ? PosFontType.fontB : PosFontType.fontA;

  PosTextSize get _bodyHeight =>
      paperSize == 80 ? PosTextSize.size2 : PosTextSize.size1;

  PosTextSize get _bodyWidth =>  paperSize == 80 ? PosTextSize.size2 : PosTextSize.size1;

  /// Characters per line based on paper size and font
  String get _separatorLine {
    if (paperSize == 80) {
      return _font == PosFontType.fontB
          ? '----------------------------------------------------------------'
          : '------------------------------------------------';
    } else {
      return _font == PosFontType.fontB
          ? '------------------------------------------'
          : '--------------------------------';
    }
  }

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

  List<int> textCenter(
    String text, {
    bool bold = false,
    PosTextSize? height,
    PosTextSize? width,
    PosFontType? fontType,
  }) {
    return generator.text(
      text,
      styles: PosStyles(
        bold: bold,
        align: PosAlign.center,
        height: height ?? _bodyHeight,
        width: width ?? _bodyWidth,
        fontType: fontType ?? _font,
      ),
    );
  }

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

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

  // ---------------------------------------------------------------------------
  // 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,
     PosTextSize? height,
    PosTextSize? width,
    PosFontType? fontType,
  }) {
    return generator.row([
      PosColumn(
        text: leftText,
        width: leftWidth,
        styles: PosStyles(
          align: PosAlign.left,
          bold: bold,
       height: height ?? _bodyHeight,
        width: width ?? _bodyWidth,
        fontType: fontType ?? _font,
        ),
      ),
      PosColumn(
        text: rightText,
        width: rightWidth,
        styles: PosStyles(
          align: PosAlign.right,
          bold: bold,
         height: height ?? _bodyHeight,
        width: width ?? _bodyWidth,
        fontType: fontType ?? _font,
        ),
      ),
    ]);
  }

  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: _bodyHeight,
        width: _bodyWidth,
      ),
    );
  }

  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,
    PosTextSize? height,
    PosTextSize? width,
    PosFontType? fontType,
  }) {
    List<int> bytes = [];
    bytes += textCenter(outletName, height: PosTextSize.size2, width: PosTextSize.size2, fontType: fontType, bold: true);
    bytes += textCenter(address, fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth);
    bytes += textCenter(phoneNumber, fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth);
    bytes += separator();
    return bytes;
  } 

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

  /// Date + time row (receipt style)
  List<int> dateTime(DateTime dateTime, { PosTextSize? height,
    PosTextSize? width,
    PosFontType? fontType,
  }) {
    return row2Columns(
      DateFormat('dd MMM yyyy').format(dateTime),
      DateFormat('HH:mm').format(dateTime),
       height: height ?? _bodyHeight,
        width: width ?? _bodyWidth,
        fontType: fontType ?? _font,
    );
  }

  /// Order info block — label : value style (checker/kitchen style)
  List<int> orderInfoSimple({
    required String orderNumber,
    String? orderType,
    required String cashierName,
    String? customerName,
  }) {
    List<int> bytes = [];
    final dateStr = DateFormat('dd-MM-yyyy HH:mm').format(DateTime.now());
    bytes += textLeft('Order    : $orderNumber');
    bytes += textLeft('Date     : $dateStr');
    
    
    if(customerName != null) {
      bytes += textLeft('Customer : $customerName');
    }
    if(orderType != null) {
       bytes += textLeft('Purpose  : ${orderType.toUpperCase()}');
    }
    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,
    PosTextSize? height,
    PosTextSize? width,
    PosFontType? fontType,
  }) {
    List<int> bytes = [];
     final dateStr = DateFormat('dd-MM-yyyy HH:mm').format(DateTime.now());
      bytes += textLeft('Order    : $orderNumber', fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth);
      bytes += textLeft('Date     : $dateStr', fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth);
       if (tableNumber != null && tableNumber.isNotEmpty) {
      bytes += textLeft('Table    : $tableNumber', fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth);
    }
      bytes += textLeft('Waiter   : $cashierName', fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth);
      bytes += textLeft('Customer : $customerName', fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth);
     
    if (paymentMethod != null) {
       bytes += textLeft('Payment  : $paymentMethod', fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth);
    }
   
    return bytes;
  }

  /// Order type banner (separator + type + separator)
  List<int> orderType(String type, {
     PosTextSize? height,
    PosTextSize? width,
    PosFontType? fontType,
  }) {
    List<int> bytes = [];
    bytes += separator();
    bytes += textCenter(type.toUpperCase(),  fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth, bold: true);
    bytes += separator();
    return bytes;
  }

    List<int> tableName(String table, {
     PosTextSize? height,
    PosTextSize? width,
    PosFontType? fontType,
  }) {
    List<int> bytes = [];
    bytes += separator();
    bytes += textCenter( 'Table : ${table.isNotEmpty ? table : '-'}',  fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth, bold: true);
    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,
     PosTextSize? height,
    PosTextSize? width,
    PosFontType? fontType,
  }) {
    List<int> bytes = [];
    final displayName = (variantName != null && variantName.isNotEmpty)
        ? '$productName ($variantName)'
        : productName;
    bytes += textLeft(displayName, bold: true, fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth);
    bytes += row2Columns('${quantity}x $unitPrice',  totalPrice, fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth,);
    if (notes != null && notes.isNotEmpty) {
      bytes += row2Columns('Note', notes, fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth, 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,
     PosTextSize? height,
    PosTextSize? width,
    PosFontType? fontType,
  }) {
    List<int> bytes = [];
    bytes += separator();
    if (totalItems > 0) {
      bytes += row2Columns('Total Item', totalItems.toString(), fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth,);
    }
    bytes += row2Columns('Subtotal', subtotal, fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth,);
    bytes += row2Columns('Diskon', discount, fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth,);
    bytes += separator();
    bytes += row2Columns('Total', total, bold: true, fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth,);
    bytes += row2Columns('Bayar', paid, fontType: fontType, height: height ?? _bodyHeight, width: width ?? _bodyWidth,);
    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);
    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));
  }
}
