<?php
defined('BASEPATH') or exit('No direct script access allowed');

use Mike42\Escpos\Printer;
use Mike42\Escpos\EscposImage;
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
use Mike42\Escpos\PrintConnectors\NetworkPrintConnector;
use Mike42\Escpos\PrintConnectors\WindowsPrintConnector;



// use Mike42\Escpos\Printer;
// use Mike42\Escpos\PrintConnectors\FilePrintConnector;
// use Mike42\Escpos\EscposImage;

class Print_m extends CI_Model
{
    public $printer;
    public $shop;
    public $shop_id;
    public $user;
    public $order_info;
    public $item_list;
    public $is_preview;
    public $receipt_content;
    public $CI;

    /**
     * Initialize the print module
     */
    public function __construct()
    {
        $this->CI = &get_instance();
        $this->receipt_content = '';
    }

    public function print_image()
    {


        // 1. Create an image with GD
        $width = 380; // Adjust for your printer
        $height = 200;
        $image = imagecreatetruecolor($width, $height);

        // Set background and text color
        $white = imagecolorallocate($image, 255, 255, 255);
        $black = imagecolorallocate($image, 0, 0, 0);
        imagefill($image, 0, 0, $white);

        // Set the font path (must be a valid TTF font that supports Bangla/Arabic)
        $fontPath = __DIR__ . '/fonts/NotoSansBengali-Regular.ttf'; // Example for Bangla

        // Draw text
        $text = "বাংলা টেক্সট প্রিন্ট";  // Bangla example
        imagettftext($image, 18, 0, 10, 50, $black, $fontPath, $text);

        // Save the image to a temp file
        $tmpFile = tempnam(sys_get_temp_dir(), 'print') . '.png';
        imagepng($image, $tmpFile);
        imagedestroy($image);

        // 2. Load the image with EscposImage (uses GD internally here)
        $connector = new FilePrintConnector("/dev/usb/lp0"); // adjust for your setup
        $printer = new Printer($connector);
        $escposImage = EscposImage::load($tmpFile, false);
        $printer->graphics($escposImage);
        $printer->cut();
        $printer->close();

        // Clean up
        unlink($tmpFile);
    }

    /**
     * Set the necessary properties for printing
     */
    public function set_properties($printer, $shop, $shop_id, $order_info, $item_list, $user, $is_preview)
    {
        $this->printer = $printer;
        $this->shop = $shop;
        $this->shop_id = $shop_id;
        $this->order_info = $order_info;
        $this->item_list = $item_list;
        $this->is_preview = $is_preview;
        $this->user = $user;
        return $this;
    }

    /**
     * Return the column width based on the shop's printer size setting.
     * 58mm → 32 cols, 80mm (default) → 42 cols.
     */
    public function getReceiptWidth(): int
    {
        $size = pos_config($this->shop->id)->printer_size ?? '58mm';
        // Default to 32 columns (58mm) as it's safer and prevents wrapping on small printers
        return ($size === '80mm') ? 42 : 32;
    }

    /**
     * Decode HTML entities and strip tags — returns clean plain text.
     */
    public function plainText(?string $str): string
    {
        return strip_tags(html_entity_decode((string) $str, ENT_QUOTES | ENT_HTML5, 'UTF-8'));
    }

    /**
     * Helper method for preview mode - adds text to the receipt content
     * 
     * @param string $text Text to add
     * @param bool $emphasis Whether text should be emphasized
     * @param string|null $justification Text justification (left, center, right)
     */
    private function cleanHtmlEntities($text)
    {
        $search = ['&nbsp;', '&amp;', '&lt;', '&gt;', '&quot;', '&#039;'];
        $replace = [' ', '&', '<', '>', '"', "'"];

        return str_replace($search, $replace, $text);
    }

    /**
     * Helper method for preview mode - adds text to the receipt content
     * 
     * @param string $text Text to add
     * @param bool $emphasis Whether text should be emphasized
     * @param string|null $justification Text justification (left, center, right)
     */
    public function add_preview_text($text, $emphasis = false, $justification = null)
    {
        // Clean HTML entities first
        $text = $this->cleanHtmlEntities($text);

        // Split the text into lines
        $lines = explode("\n", $text);

        foreach ($lines as $line) {
            $formatted_line = $line;

            // Skip empty lines but add the newline
            if (trim($formatted_line) === '') {
                $this->receipt_content .= "\n";
                continue;
            }

            // Set the width for the receipt (adjust based on your printer's width)
            $width = 48;

            // Apply justification
            if ($justification == Printer::JUSTIFY_CENTER) {
                // For center justification
                $padding = $width - mb_strlen($formatted_line);
                if ($padding > 0) {
                    $left_pad = floor($padding / 2);
                    $formatted_line = str_repeat(' ', $left_pad) . $formatted_line;
                }
            } else if ($justification == Printer::JUSTIFY_RIGHT) {
                // For right justification
                $padding = $width - mb_strlen($formatted_line);
                if ($padding > 0) {
                    $formatted_line = str_repeat(' ', $padding) . $formatted_line;
                }
            }

            // Apply emphasis (bold)
            if ($emphasis) {
                $formatted_line = '*' . $formatted_line . '*';
            }

            // Add the formatted line to receipt content with a newline
            $this->receipt_content .= $formatted_line . "\n";
        }
    }

    /**
     * Add right-aligned text with left-aligned label (for prices)
     * 
     * @param string $label Left-aligned label
     * @param string $value Right-aligned value
     */
    public function add_preview_price_line($label, $value)
    {
        // Clean any HTML entities
        $label = $this->cleanHtmlEntities($label);
        $value = $this->cleanHtmlEntities($value);

        $width = 48;
        $padding = $width - mb_strlen($label) - mb_strlen($value);
        if ($padding > 0) {
            $line = $label . str_repeat(' ', $padding) . $value;
        } else {
            // If not enough space, put on next line
            $line = $label . "\n" . str_pad($value, $width, ' ', STR_PAD_LEFT);
        }
        $this->receipt_content .= $line . "\n";
    }
    /**
     * Get the receipt content for preview
     */
    public function get_receipt_content()
    {
        return $this->receipt_content;
    }

    /**
     * Print the receipt header with shop information
     */
    public function printHeader()
    {
        if ($this->is_preview) {
            // Generate preview header content
            $shop_name = !empty($this->shop->name) ? $this->shop->name : $this->shop->username;
            $this->add_preview_text($shop_name, true, Printer::JUSTIFY_CENTER);
            $this->add_preview_text("", false);

            // Order details
            $this->add_preview_text(\lang('order_id') . ': #' . $this->order_info->uid);
            $this->add_preview_text($this->CI->lang->line('order_type') . ': ' . order_type($this->order_info->order_type));

            // Table info if applicable
            if (isset($this->order_info->table_no) && !empty($this->order_info->table_no)) {
                $this->add_preview_text(lang('table') . ': ' . __table($this->order_info->table_no)->area_name . ' / ' .
                    __table($this->order_info->table_no)->name);
            }

            // Hotel info for room service
            if (isset($this->order_info->order_type) && $this->order_info->order_type == 8) {
                if (isset($this->order_info->hotel_id) && !empty($this->order_info->hotel_id)) {
                    $this->add_preview_text(lang('hotel_name') . ': ' .
                        single_select_by_id($this->order_info->hotel_id, 'hotel_list')['hotel_name']);
                    $this->add_preview_text(lang('room_number') . ': ' . $this->order_info->room_number);
                }
            }

            // Date
            $this->add_preview_text(lang('date') . ': ' . full_time($this->order_info->created_at));

            // Shop details if not guest login
            if ($this->order_info->is_guest_login != 1) {
                if (!empty($this->shop->address)) {
                    $this->add_preview_text(lang('address') . ': ' . $this->shop->address);
                }
                $this->add_preview_text(lang('email') . ': ' . (!empty($this->shop->email) ? $this->shop->email : ''));
                $this->add_preview_text(\lang('phone') . ': ' . (!empty($this->shop->phone) ? $this->shop->phone : ''));
                if (isset($this->shop->tax_number) && !empty($this->shop->tax_number)) {
                    $this->add_preview_text(lang('tax_number') . ': ' . $this->shop->tax_number);
                }
            }
            $this->add_preview_text(str_repeat('-', 48));
        } else {
            // Actual printing
            // Print shop name
            $this->printer->setJustification(Printer::JUSTIFY_CENTER);
            $this->printer->setEmphasis(true);
            $this->printer->setTextSize(2, 2);
            $this->printer->text(!empty($this->shop->name) ? $this->shop->name : $this->shop->username);
            $this->printer->setTextSize(1, 1);
            $this->printer->feed();
            $this->printer->setEmphasis(false);
            // Print order details
            $this->printer->text(lang('order_id') . ': #' . $this->order_info->uid . "\n");
            $this->printer->text(lang('order_type') . ': ' . order_type($this->order_info->order_type) . "\n");
            // Print table info if applicable
            if (isset($this->order_info->table_no) && !empty($this->order_info->table_no)) {
                $this->printer->text(lang('table') . ': ' . __table($this->order_info->table_no)->area_name . ' / ' .
                    __table($this->order_info->table_no)->name . "\n");
            }
            // Print hotel info for room service
            if (isset($this->order_info->order_type) && $this->order_info->order_type == 8) {
                if (isset($this->order_info->hotel_id) && !empty($this->order_info->hotel_id)) {
                    $this->printer->text(lang('hotel_name') . ': ' .
                        single_select_by_id($this->order_info->hotel_id, 'hotel_list')['hotel_name'] . "\n");
                    $this->printer->text(lang('room_number') . ': ' . $this->order_info->room_number . "\n");
                }
            }
            // Print date
            $this->printer->text(lang('date') . ': ' . full_time($this->order_info->created_at) . "\n");
            // Print shop details if not guest login
            if ($this->order_info->is_guest_login != 1) {
                if (!empty($this->shop->address)) {
                    $this->printer->text(lang('address') . ': ' . $this->shop->address . "\n");
                }
                $this->printer->text(lang('email') . ': ' . (!empty($this->shop->email) ? $this->shop->email : '') . "\n");
                $this->printer->text(lang('phone') . ': ' . (!empty($this->shop->phone) ? $this->shop->phone : '') . "\n");
                if (isset($this->shop->tax_number) && !empty($this->shop->tax_number)) {
                    $this->printer->text(lang('tax_number') . ': ' . $this->shop->tax_number . "\n");
                }
            }
            $this->printer->text(str_repeat('-', 48) . "\n");
        }
    }

    /**
     * Print customer information
     */
    public function printCustomerInfo()
    {
        if ($this->is_preview) {
            if ($this->order_info->order_type == 7 && $this->order_info->table_no != 0) {
                $this->add_preview_text(lang('customer_details') . ': ' . lang('package_restaurant_dine_in'));
            } else {
                $this->add_preview_text(lang('customer_details') . ': ');
                if (!empty($this->order_info->name)) {
                    $this->add_preview_text(lang('name') . ': ' . $this->order_info->name);
                } else {
                    $this->add_preview_text(lang('name') . ': ' . lang('walk_in_customer'));
                }

                if (!empty($this->order_info->phone)) {
                    $this->add_preview_text(lang('phone') . ': ' . $this->order_info->phone);
                }
                if (!empty($this->order_info->address)) {
                    $this->add_preview_text(lang('address') . ': ' . $this->order_info->address);
                }
                // Delivery information
                if ($this->order_info->order_type == 1) {
                    $shpping_info = $this->CI->common_m->delivery_area_by_shop_id($this->order_info->shipping_id, $this->shop_id);
                    if (isset($shpping_info['area']) && !empty($shpping_info['area'])) {
                        $this->add_preview_text(lang('delivery_area') . ': ' . $shpping_info['area']);
                    }
                    if (!empty($this->order_info->delivery_area)) {
                        $this->add_preview_text(lang('shipping_address') . ': ' . $this->order_info->delivery_area);
                    }
                }
            }
            $this->add_preview_text(str_repeat('-', 48));
        } else {
            if ($this->order_info->order_type == 7 && $this->order_info->table_no != 0) {
                $this->printer->text(lang('customer_details') . ': ' . lang('package_restaurant_dine_in') . "\n");
            } else {
                $this->printer->text(lang('customer_details') . ': ' . $this->order_info->name . "\n");
                if (!empty($this->order_info->phone)) {
                    $this->printer->text(lang('phone') . ': ' . $this->order_info->phone . "\n");
                }
                if (!empty($this->order_info->address)) {
                    $this->printer->text(lang('address') . ': ' . $this->order_info->address . "\n");
                }
                // Delivery information
                if ($this->order_info->order_type == 1) {
                    $shpping_info = $this->CI->common_m->delivery_area_by_shop_id($this->order_info->shipping_id, $this->shop_id);
                    if (isset($shpping_info['area']) && !empty($shpping_info['area'])) {
                        $this->printer->text(lang('delivery_area') . ': ' . $shpping_info['area'] . "\n");
                    }
                    if (!empty($this->order_info->delivery_area)) {
                        $this->printer->text(lang('shipping_address') . ': ' . $this->order_info->delivery_area . "\n");
                    }
                }
            }
            $this->printer->text(str_repeat('-', 48) . "\n");
        }
    }

    public function printOrderItems()
    {
        // ── Width: 32 cols for 58mm, 42 for 80mm ─────────────────────────────
        $w = $this->getReceiptWidth();

        // ── Helper: format extras as plain-text bullet lines ──────────────────
        $formatExtras = function ($extra_id, $extra_qty, $item_id) {
            if (empty($extra_id) || !isJson($extra_id)) return '';
            $lines = [];
            foreach (json_decode($extra_id) as $ex) {
                $ex_qty  = extra_qty($extra_qty, $ex);
                $ex_info = extras($ex, $item_id);
                $ex_name  = $this->plainText($ex_info->ex_name ?? '');
                $ex_price = $ex_info->ex_price ?? 0;
                $total    = $ex_qty * $ex_price;
                $lines[]  = "  - {$ex_qty} x {$ex_name} (" . number_format($ex_price, 2) . ") = " . number_format($total, 2);
            }
            return implode("\n", $lines);
        };

        // ── Dine-in package orders ─────────────────────────────────────────────
        if ($this->order_info->order_type == 7 && $this->order_info->table_no == 0) {
            $get_dinein_items = $this->CI->admin_m->get_dinin_items($this->order_info->dine_id);
            foreach ($get_dinein_items as $package) {
                if ($this->is_preview) {
                    $this->add_preview_text($this->plainText($package['package_name']), true, Printer::JUSTIFY_LEFT);
                    foreach ($package['all_items'] as $item) {
                        $this->add_preview_text("  1 x " . $this->plainText($item['title']), false, Printer::JUSTIFY_LEFT);
                        $this->add_preview_text(currency_format($item['item_price'], $this->shop_id), false, Printer::JUSTIFY_RIGHT);
                    }
                } else {
                    $this->printer->setJustification(Printer::JUSTIFY_LEFT);
                    $this->printer->setEmphasis(true);
                    $this->printer->text($this->plainText($package['package_name']) . "\n");
                    $this->printer->setEmphasis(false);
                    foreach ($package['all_items'] as $item) {
                        $this->printer->text("  1 x " . $this->plainText($item['title']) . "\n");
                        $this->printer->text("      " . currency_format($item['item_price'], $this->shop_id) . "\n");
                    }
                    $this->printer->feed();
                }
            }
            return;
        }

        // ── Regular orders ─────────────────────────────────────────────────────
        // item_list is a flat array of rows (arrays) from get_customer_order_item_list
        foreach ($this->item_list as $row) {
            // Normalize: support both array and object rows
            $row = is_object($row) ? (array) $row : $row;

            // ── Build item name ──────────────────────────────────────────────
            if (!empty($row['is_package']) && $row['is_package'] == 1) {
                $item_name = $this->plainText($row['package_name'] ?? 'Package');
            } else {
                $item_name = $this->plainText($row['name'] ?? ($row['title'] ?? ''));
                if (!empty($row['is_size']) && $row['is_size'] == 1) {
                    $variant = $this->plainText(variants($row['size_slug'], $row['item_id'], $row['shop_id']));
                    $item_name .= " [{$variant}]";
                }
            }

            // Tax status label e.g. "(Inc. Tax)"
            $tax_label = $this->plainText(__taxStatus(shop($this->shop_id)->is_tax, (object)$row));

            // ── Qty × price line and subtotal ────────────────────────────────
            $qty_price = "  " . $row['qty'] . " x " . currency_format($row['item_price'], $this->shop_id);
            $sub_total = currency_format($row['sub_total'], $this->shop_id);

            // ── Extras block (plain text) ────────────────────────────────────
            $extras_text = '';
            if (!empty($row['is_extras']) && $row['is_extras'] == 1) {
                $extras_text = $formatExtras($row['extra_id'], $row['extra_qty'], $row['item_id']);
            }

            // ── Item comments (if feature is enabled) ────────────────────────
            $comment_text = '';
            if (pos_config($this->shop->id)->is_comments == 1 && !empty($row['item_comments'])) {
                $comment_text = "  Note: " . $this->plainText($row['item_comments']);
            }

            // ── PREVIEW MODE ─────────────────────────────────────────────────
            if ($this->is_preview) {
                if ($tax_label) {
                    $this->add_preview_text("{$item_name} ({$tax_label})", true, Printer::JUSTIFY_LEFT);
                } else {
                    $this->add_preview_text("{$item_name}", true, Printer::JUSTIFY_LEFT);
                }

                // Qty × price aligned with subtotal on same line if it fits
                $spaces = $w - mb_strlen($qty_price) - mb_strlen($sub_total);
                if ($spaces >= 1) {
                    $this->add_preview_text($qty_price . str_repeat(' ', $spaces) . $sub_total, false, Printer::JUSTIFY_LEFT);
                } else {
                    $this->add_preview_text($qty_price, false, Printer::JUSTIFY_LEFT);
                    $this->add_preview_text($sub_total, false, Printer::JUSTIFY_RIGHT);
                }

                if ($extras_text !== '') {
                    foreach (explode("\n", $extras_text) as $line) {
                        $this->add_preview_text($line, false, Printer::JUSTIFY_LEFT);
                    }
                }

                if ($comment_text !== '') {
                    $this->add_preview_text($comment_text, false, Printer::JUSTIFY_LEFT);
                }

                $this->add_preview_text(''); // blank line between items

            // ── ACTUAL PRINT MODE ─────────────────────────────────────────────
            } else {
                $this->printer->setJustification(Printer::JUSTIFY_LEFT);

                // Item name (bold)
                $this->printer->setEmphasis(true);
                if ($tax_label) {
                    $this->printer->text("{$item_name} ({$tax_label})\n");
                } else {
                    $this->printer->text("{$item_name}\n");
                }
                $this->printer->setEmphasis(false);

                // Qty × price + subtotal on same line, padded to receipt width
                $spaces = $w - mb_strlen($qty_price) - mb_strlen($sub_total);
                if ($spaces >= 1) {
                    $this->printer->text($qty_price . str_repeat(' ', $spaces) . $sub_total . "\n");
                } else {
                    $this->printer->text($qty_price . "\n");
                    $this->printer->setJustification(Printer::JUSTIFY_RIGHT);
                    $this->printer->text($sub_total . "\n");
                    $this->printer->setJustification(Printer::JUSTIFY_LEFT);
                }

                // Extras
                if ($extras_text !== '') {
                    $this->printer->text($extras_text . "\n");
                }

                // Comment
                if ($comment_text !== '') {
                    $this->printer->text($comment_text . "\n");
                }

                $this->printer->feed(); // blank line between items
            }
        }
    }

    /**
     * Print order totals with improved spacing
     */
    public function printOrderTotals()
    {
        $p = __order($this->order_info, $this->item_list);

        // Define receipt width based on printer type
        $receipt_width = $this->getReceiptWidth();

        if ($this->is_preview) {
            // Generate preview content
            $this->add_preview_text(str_repeat('-', $receipt_width));

            // Define a function for preview price lines
            $add_preview_price_line = function ($label, $value) use ($receipt_width) {
                $clean_label = trim($this->plainText($label));
                $clean_value = trim($this->plainText($value));
                $spaces = $receipt_width - mb_strwidth($clean_label, 'UTF-8') - mb_strwidth($clean_value, 'UTF-8');
                $space_str = $spaces > 0 ? str_repeat(' ', $spaces) : ' ';
                $this->add_preview_text($clean_label . $space_str . $clean_value);
            };

            // Print subtotal
            $add_preview_price_line(lang('sub_total'), currency_format($p->subtotal, $this->shop_id));

            // Shipping
            if ($p->shipping != 0) {
                $add_preview_price_line(lang('shipping'), currency_format($p->shipping, $this->shop_id));
            }

            // Tax
            if (!empty($p->tax_details)) {
                foreach ($p->tax_details as $tax) {
                    $add_preview_price_line(
                        lang('tax') . ' ' . tax($tax['percent'], $tax['tax_status']),
                        currency_format($tax['total_price'], $this->shop_id)
                    );
                }
            } else {
                if ($p->tax_fee != 0) {
                    $add_preview_price_line(lang('tax'), currency_format($p->tax_fee, $this->shop_id));
                }
            }

            // Tips
            if ($p->tips != 0) {
                $add_preview_price_line(lang('tips'), currency_format($p->tips, $this->shop_id));
            }

            // Service charge
            if ($p->service_charge != 0) {
                $add_preview_price_line(lang('service_charge'), currency_format($p->service_charge, $this->shop_id));
            }

            // Discount
            if ($p->discount != '0') {
                $add_preview_price_line(lang('discount'), currency_format($p->discount, $this->shop_id));
            }

            // Coupon discount
            if ($p->coupon_discount != 0) {
                $add_preview_price_line(
                    lang('coupon_discount') . ' (' . $p->coupon_percent . ' %)',
                    currency_format($p->coupon_discount, $this->shop_id)
                );
            }

            // Grand total
            $grand_total_label = "*" . trim($this->plainText(lang('grand_total'))) . "*";
            $grand_total_value = "*" . trim($this->plainText(currency_format($p->grand_total, $this->shop_id))) . "*";
            $spaces = $receipt_width - mb_strwidth($grand_total_label, 'UTF-8') - mb_strwidth($grand_total_value, 'UTF-8');
            $space_str = $spaces > 0 ? str_repeat(' ', $spaces) : ' ';

            $this->add_preview_text($grand_total_label . $space_str . $grand_total_value);
            $this->add_preview_text(str_repeat('-', $receipt_width));
        } else {
            // Actual printing
            $this->printer->text(str_repeat('-', $receipt_width) . "\n");

            // Function to print price line with proper spacing
            $printPriceLine = function ($label, $value) use ($receipt_width) {
                $clean_label = trim($this->plainText($label));
                $clean_value = trim($this->plainText($value));
                // Calculate the space needed
                $spaces = $receipt_width - mb_strwidth($clean_label, 'UTF-8') - mb_strwidth($clean_value, 'UTF-8');

                if ($spaces >= 1) {
                    // We have enough space for a single line
                    $this->printer->text($clean_label . str_repeat(' ', $spaces) . $clean_value . "\n");
                } else {
                    // Fallback to single space instead of wrapping
                    $this->printer->text($clean_label . " " . $clean_value . "\n");
                }
            };

            // Print subtotal
            $printPriceLine(lang('sub_total'), currency_format($p->subtotal, $this->shop_id));

            // Shipping
            if ($p->shipping != 0) {
                $printPriceLine(lang('shipping'), currency_format($p->shipping, $this->shop_id));
            }

            // Tax
            if (!empty($p->tax_details)) {
                foreach ($p->tax_details as $tax) {
                    $printPriceLine(
                        lang('tax') . ' ' . tax($tax['percent'], $tax['tax_status']),
                        currency_format($tax['total_price'], $this->shop_id)
                    );
                }
            } else {
                if ($p->tax_fee != 0) {
                    $printPriceLine(lang('tax'), currency_format($p->tax_fee, $this->shop_id));
                }
            }

            // Tips
            if ($p->tips != 0) {
                $printPriceLine(lang('tips'), currency_format($p->tips, $this->shop_id));
            }

            // Service charge
            if ($p->service_charge != 0) {
                $printPriceLine(lang('service_charge'), currency_format($p->service_charge, $this->shop_id));
            }

            // Discount
            if ($p->discount != '0') {
                $printPriceLine(lang('discount'), currency_format($p->discount, $this->shop_id));
            }

            // Coupon discount
            if ($p->coupon_discount != 0) {
                $printPriceLine(
                    lang('coupon_discount') . ' (' . $p->coupon_percent . ' %)',
                    currency_format($p->coupon_discount, $this->shop_id)
                );
            }

            // Grand total - with emphasis
            $this->printer->setEmphasis(true);
            $grandTotalLabel = trim($this->plainText(lang('grand_total')));
            $grandTotalValue = trim($this->plainText(currency_format($p->grand_total, $this->shop_id)));
            $spaces = $receipt_width - mb_strwidth($grandTotalLabel, 'UTF-8') - mb_strwidth($grandTotalValue, 'UTF-8');

            if ($spaces >= 1) {
                $this->printer->text($grandTotalLabel . str_repeat(' ', $spaces) . $grandTotalValue . "\n");
            } else {
                $this->printer->text($grandTotalLabel . " " . $grandTotalValue . "\n");
            }

            $this->printer->setEmphasis(false);
            $this->printer->text(str_repeat('-', $receipt_width) . "\n");
        }
    }


    /**
     * Print payment information
     */
    public function printPaymentInfo()
    {
        $p = __order($this->order_info, $this->item_list);
        $receipt_width = $this->getReceiptWidth();

        if ($this->is_preview) {
            $add_preview_line = function ($label, $value) use ($receipt_width) {
                $clean_label = trim($this->plainText($label));
                $clean_value = trim($this->plainText($value));
                $spaces = $receipt_width - mb_strwidth($clean_label, 'UTF-8') - mb_strwidth($clean_value, 'UTF-8');
                $space_str = $spaces > 0 ? str_repeat(' ', $spaces) : ' ';
                $this->add_preview_text($clean_label . $space_str . $clean_value);
            };

            $payment_method = ($this->order_info->order_type == 5 || $this->order_info->is_payment == 1) ? ucfirst($this->order_info->payment_by) : lang('cash');
            
            $add_preview_line(lang('payment_by'), $payment_method);
            $add_preview_line(lang('amount'), currency_format($p->grand_total, $this->shop_id));
            $add_preview_line(lang('status'), ($this->order_info->is_payment == 1 ? lang('paid') : lang('unpaid')));
            
            if (isset($this->order_info->staff_id) && !empty($this->order_info->staff_id)) {
                $add_preview_line(lang('staff'), __staff($this->order_info->staff_id)->name);
            }
        } else {
            $print_line = function ($label, $value) use ($receipt_width) {
                $clean_label = trim($this->plainText($label));
                $clean_value = trim($this->plainText($value));
                $spaces = $receipt_width - mb_strwidth($clean_label, 'UTF-8') - mb_strwidth($clean_value, 'UTF-8');

                if ($spaces >= 1) {
                    $this->printer->text($clean_label . str_repeat(' ', $spaces) . $clean_value . "\n");
                } else {
                    $this->printer->text($clean_label . " " . $clean_value . "\n");
                }
            };

            $payment_method = ($this->order_info->order_type == 5 || $this->order_info->is_payment == 1) ? ucfirst($this->order_info->payment_by) : lang('cash');
            
            $print_line(lang('payment_by'), $payment_method);
            $print_line(lang('amount'), currency_format($p->grand_total, $this->shop_id));
            $print_line(lang('status'), ($this->order_info->is_payment == 1 ? lang('paid') : lang('unpaid')));
            
            if (isset($this->order_info->staff_id) && !empty($this->order_info->staff_id)) {
                $print_line(lang('staff'), __staff($this->order_info->staff_id)->name);
            }
            $this->printer->feed();
        }
    }

    public function printFooter()
    {
        if ($this->is_preview) {
            $this->add_preview_text("", false, Printer::JUSTIFY_CENTER); // Empty line

            // Print welcome message if configured
            if (!empty(pos_config($this->shop->id)->welcome_message)) {
                $this->add_preview_text($this->plainText(pos_config($this->shop->id)->welcome_message), false, Printer::JUSTIFY_CENTER);
            }

            // Print order comments if enabled
            if (isset(pos_config($this->shop->id)->is_comments) && pos_config($this->shop->id)->is_comments == 1) {
                if (isset($this->order_info->comments) && !empty($this->order_info->comments)) {
                    $this->add_preview_text($this->plainText($this->order_info->comments), false, Printer::JUSTIFY_CENTER);
                }
            }

            // Add QR code if available
            if (isset($this->user->qr_link) && !empty($this->user->qr_link)) {
                $qr_image_url = asset_url($this->user->qr_link);
                $this->add_preview_image($qr_image_url, Printer::JUSTIFY_CENTER);
            }
        } else {
            // Actual printing code remains unchanged
            $this->printer->setJustification(Printer::JUSTIFY_CENTER);
            if (!empty(pos_config($this->shop->id)->welcome_message)) {
                $this->printer->text($this->plainText(pos_config($this->shop->id)->welcome_message) . "\n");
                $this->printer->feed();
            }

            if (isset(pos_config($this->shop->id)->is_comments) && pos_config($this->shop->id)->is_comments == 1) {
                if (isset($this->order_info->comments) && !empty($this->order_info->comments)) {
                    $this->printer->text($this->plainText($this->order_info->comments) . "\n");
                    $this->printer->feed();
                }
            }

            if (isset($this->user->qr_link) && !empty($this->user->qr_link)) {
                try {
                    if (strpos($this->user->qr_link, 'http') === 0) {
                        $qr_image_url = $this->user->qr_link;
                    } else {
                        $qr_image_url = asset_url($this->user->qr_link);
                    }

                    $qr_image = EscposImage::load($qr_image_url, false);

                    $this->printer->graphics($qr_image);
                    $this->printer->text("\nScan QR Code for more information\n");
                } catch (Exception $e) {
                    error_log('QR printing error: ' . $e->getMessage() . ' | Path: ' . $qr_image_url);
                    $this->printer->text("QR Code Available\n");
                }
                $this->printer->feed();
            }
            $this->printer->feed(2);
        }
    }

    public function add_preview_image($image_url, $justification = Printer::JUSTIFY_CENTER)
    {
        // For HTML preview mode, we'll add properly formatted HTML 
        $align = $this->get_justification_style($justification);

        // Create a unique ID for this image to prevent issues with multiple QR codes
        $img_id = 'qr_' . md5($image_url . microtime());

        $this->receipt_content .= "\n"; // Add a line break before the image
        $this->receipt_content .= '<div style="text-align: ' . $align . '; margin: 10px 0;">';
        $this->receipt_content .= '<img id="' . $img_id . '" src="' . $image_url . '" alt="QR Code" style="max-width: 200px; height: auto;" onerror="this.style.display=\'none\'; document.getElementById(\'qr_error\').style.display=\'block\';" />';
        $this->receipt_content .= '<div id="qr_error" style="display:none;">QR Code Available</div>';
        $this->receipt_content .= '</div>';
        $this->receipt_content .= '<div style="text-align: ' . $align . ';">';
        $this->receipt_content .= '<small>Scan QR Code for more information</small>';
        $this->receipt_content .= '</div>';
        $this->receipt_content .= "\n"; // Add a line break after the image
    }

    private function get_justification_style($justification)
    {
        switch ($justification) {
            case Printer::JUSTIFY_LEFT:
                return 'left';
            case Printer::JUSTIFY_RIGHT:
                return 'right';
            case Printer::JUSTIFY_CENTER:
            default:
                return 'center';
        }
    }
}
