import time
from datetime import datetime

from PyQt5.QtWidgets import QApplication

from src.components.os_label_printer import *
from src.lib.helpers import ConfigReader

SYSTEM_ID = "test-linux"
START_SN = 100
QTY = 1
STOP_SN = START_SN + QTY

TEMPLATE = "Lamborghini_30x16_203.prn"
PRINTER_NAME = "zd421"
PN = "07N131628A"
#PN = "07N131597A"

config = ConfigReader(system_id=SYSTEM_ID)
printer = Os_Label_Printer(config=config, name="label_printer")
barcode_prefix = f"#{PN}    ###*1IT ECE"

barcode_suffix = "*="

barcode_format = "{barcode_prefix}{SN7}{check}{barcode_suffix}"
module_data_format ="1IT ECE{SN7}"

def main():
    app = QApplication(sys.argv)
    for sn in range(START_SN, STOP_SN + 1):
        timenow = datetime.now()
        print(f"PRINTING LABEL # {sn}")
        context = {
            "PART": PN,
            "SN": str(sn),
            "SN4": f"{sn:0>4}",
            "SN5": f"{sn:0>5}",
            "SN6": f"{sn:0>6}",
            "SN7": f"{sn:0>7}",
            "DATETIME": timenow.strftime("%d/%m/%Y %H:%M:%S"),
            "DATE": timenow.strftime("%d/%m/%Y"),
            "TIME": timenow.strftime("%H:%M:%S"),
            "YYYY": timenow.strftime("%Y"),
            "YY": timenow.strftime("%y"),
            "MO": timenow.strftime("%m"),
            "DD": timenow.strftime("%d"),
            "HH": timenow.strftime("%H"),
            "MI": timenow.strftime("%M"),
            "SS": timenow.strftime("%S"),
            "JJJ": timenow.strftime("%j"),
            "WW": timenow.strftime("%W"),
            "SUPPLY": "10231",
        }
        formatted_module_data = module_data_format.format(**context)
        check= calculate_modulo43_checksum(formatted_module_data)
        context.update(
            {
                "barcode_prefix": barcode_prefix,
                "check": check,
                "barcode_suffix": barcode_suffix,
            }
        )

        formatted_barcode = barcode_format.format(**context)
        context['BCODE'] = formatted_barcode

        printer.print_label(TEMPLATE, context)

        time.sleep(1)


def calculate_modulo43_checksum(data_sequence: str) -> str:
    """
    Calculates the Modulo 43 checksum for a given data sequence.

    The function determines the checksum value for each character based on a
    predefined assignment table, calculates the total sum of these values,
    and then finds the remainder of the division by 43. The character
    corresponding to this remainder is the check digit.

    Args:
        data_sequence: The input string for which to calculate the checksum.

    Returns:
        The Modulo 43 check digit as a single character.

    Raises:
        ValueError: If the data_sequence contains a character not found in the
                    assignment table.
    """
    assignment_table = {
        '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
        'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15, 'G': 16, 'H': 17, 'I': 18,
        'J': 19, 'K': 20, 'L': 21, 'M': 22, 'N': 23, 'O': 24, 'P': 25, 'Q': 26, 'R': 27,
        'S': 28, 'T': 29, 'U': 30, 'V': 31, 'W': 32, 'X': 33, 'Y': 34, 'Z': 35,
        '-': 36, '.': 37, ' ': 38, '$': 39, '/': 40, '+': 41, '%': 42
    }

    total_sum = 0
    for char in data_sequence:
        if char in assignment_table:
            total_sum += assignment_table[char]
        else:
            raise ValueError(f"Character '{char}' is not valid for checksum calculation.")

    remainder = total_sum % 43

    # Invert the assignment_table to map the remainder back to the character
    for char, value in assignment_table.items():
        if value == remainder:
            return char

    # This part of the code should be unreachable given the logic
    return "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"


if __name__ == "__main__":
    main()
