import sys
import json
import base64
import win32print


# ============================================================
# PRINTER
# ============================================================

PRINTER_NAME = "SNBC TVSE LP 46 NEO BPLE"

STICKER_WIDTH_MM = 50
STICKER_HEIGHT_MM = 25

COLUMN_GAP_MM = 3
ROW_GAP_MM = 3

DOTS_PER_MM = 8

BRAND_NAME = "PICK MY SNACKS"

TOP_MARGIN_DOTS = 22
LEFT_MARGIN_DOTS = 45
RIGHT_COLUMN_X = 185

BRAND_FONT = "2"
PRODUCT_FONT = "3"
QR_CELL_SIZE = 4

FONT_CHAR_WIDTH_DOTS = {
    "1": 8,
    "2": 12,
    "3": 16
}

ROW_WIDTH_MM = (
    STICKER_WIDTH_MM * 2
) + COLUMN_GAP_MM

STICKER_WIDTH_DOTS = (
    STICKER_WIDTH_MM * DOTS_PER_MM
)


# ============================================================
# CENTER TEXT
# ============================================================

def centered_x(text, font, region_width):

    char_width = FONT_CHAR_WIDTH_DOTS.get(font, 12)

    text_width = len(text) * char_width

    return max(
        0,
        (region_width - text_width) // 2
    )


# ============================================================
# ONE STICKER
# ============================================================
def sticker_block(x_offset, item):
    
    x = lambda value: x_offset + value

    brand_x = centered_x(
        BRAND_NAME,
        BRAND_FONT,
        STICKER_WIDTH_DOTS
    )

    y_brand = TOP_MARGIN_DOTS
    y_product = y_brand + 24

    # QR moved upward
    y_qr = y_product + 20

    # Batch below QR
    y_batch = y_qr + 105

    return (
        f'TEXT {x(brand_x)},{y_brand},"{BRAND_FONT}",0,1,1,"{BRAND_NAME}"\n'

        f'TEXT {x(LEFT_MARGIN_DOTS)},{y_product},"{PRODUCT_FONT}",0,1,1,"{item["product_name"]}"\n'

        f'QRCODE {x(LEFT_MARGIN_DOTS)},{y_qr},H,{QR_CELL_SIZE},A,0,"{item["qr_data"]}"\n'

        f'TEXT {x(LEFT_MARGIN_DOTS)},{y_batch},"2",0,1,1,"{item["batch_code"]}"\n'

        f'TEXT {x(RIGHT_COLUMN_X)},{y_qr},"2",0,1,1,"Price"\n'

        f'TEXT {x(RIGHT_COLUMN_X)},{y_qr + 22},"2",0,1,1,"Rs {item["price"]}"\n'

        f'TEXT {x(RIGHT_COLUMN_X)},{y_qr + 52},"2",0,1,1,"Pkd: {item["pkd_date"]}"\n'

        f'TEXT {x(RIGHT_COLUMN_X)},{y_qr + 76},"2",0,1,1,"Exp: {item["exp_date"]}"\n'
    )
# ============================================================
# BUILD ONE ROW
# ============================================================

def build_row(left_item, right_item):

    sticker_width_dots = (
        STICKER_WIDTH_MM * DOTS_PER_MM
    )

    gap_dots = (
        COLUMN_GAP_MM * DOTS_PER_MM
    )

    tspl = "CLS\n"

    tspl += sticker_block(
        0,
        left_item
    )

    right_x = (
        sticker_width_dots
        + gap_dots
    )

    tspl += sticker_block(
        right_x,
        right_item
    )

    tspl += "PRINT 1,1\n"

    return tspl


# ============================================================
# SEND TO PRINTER
# ============================================================

def print_label(tspl):

    printer = win32print.OpenPrinter(
        PRINTER_NAME
    )

    try:

        job_info = (
            "Laravel QR Label",
            None,
            "RAW"
        )

        win32print.StartDocPrinter(
            printer,
            1,
            job_info
        )

        try:

            win32print.StartPagePrinter(
                printer
            )

            win32print.WritePrinter(
                printer,
                tspl.encode("utf-8")
            )

            win32print.EndPagePrinter(
                printer
            )

        finally:

            win32print.EndDocPrinter(
                printer
            )

    finally:

        win32print.ClosePrinter(
            printer
        )


# ============================================================
# MAIN
# ============================================================

if __name__ == "__main__":

    # Laravel MUST send product data

    if len(sys.argv) < 2:

        print("ERROR: No Laravel product data received.")

        sys.exit(1)


    try:

        encoded_data = sys.argv[1]

        decoded = base64.b64decode(
            encoded_data
        ).decode("utf-8")

        data = json.loads(
            decoded
        )

    except Exception as e:

        print(
            "ERROR: Could not decode Laravel data:",
            e
        )

        sys.exit(1)


    # ========================================================
    # IMPORTANT
    # This item comes ONLY from Laravel.
    # There is NO CHANNA KADALAI here.
    # ========================================================

    item = {

        "qr_data": str(
            data.get("qr_data", "")
        ),

        "product_name": str(
            data.get("product_name", "")
        ),

        "batch_code": str(
            data.get("batch_code", "")
        ),

        "price": str(
            data.get("price", "")
        ),

        "pkd_date": str(
            data.get("packed_date", "")
        ),

        "exp_date": str(
            data.get("expiry_date", "")
        )

    }


    # ========================================================
    # PRINT EXACTLY TWO STICKERS
    # ========================================================

    tspl = (

        f"SIZE {ROW_WIDTH_MM} mm, "
        f"{STICKER_HEIGHT_MM} mm\n"

        f"GAP {ROW_GAP_MM} mm, 0 mm\n"

        "DIRECTION 1\n"

        "REFERENCE 0,0\n"

        + build_row(
            item,
            item
        )
    )


    # ========================================================
    # PRINT
    # ========================================================

    try:

        print("================================")
        print("Laravel product received:")
        print("Product:", item["product_name"])
        print("Price:", item["price"])
        print("Batch:", item["batch_code"])
        print("QR:", item["qr_data"])
        print("================================")

        print_label(tspl)

        print(
            "PRINT SUCCESS:",
            item["product_name"]
        )

    except Exception as e:

        print(
            "PRINTER ERROR:",
            e
        )

        sys.exit(1)