from flask import current_app
import os
import ctypes
import datetime

# Build path
dllPath = os.path.join(os.path.abspath(os.path.dirname(__file__)), "RS232.DLL")

# Load the RS232 DLL
api = ctypes.WinDLL(dllPath)

# Create a map to RS232() function
send_data_raw = api.RS232
send_data_raw.argtypes = [ctypes.c_char_p]
send_data_raw.restype = ctypes.c_char_p

TAG_NAMES = {
    "001": "TM",
    "002": "MT",
    "003": "NCAI",
    "004": "NS",
    "005": "NSA",
    "006": "NHC",
    "007": "NCAR",
    "008": "STAN",
    "009": "NA",
    "010": "DP",
    "011": "CB",
    "012": "DE",
    "013": "CR",
    "014": "DA",
    "015": "HE",
    "016": "NPRT",
    "017": "DAEX",
    "018": "DATR",
    "019": "HETR",
    "020": "TIDE",
    "021": "TYPA",
    "022": "RE",
    "023": "RECB",
    "024": "REQU",
    "025": "RESE",
    "026": "RECO",
    "027": "RERA",
    "030": "DP1",
    "031": "DP2",
    "032": "DP3",
    "033": "DP4",
}

TAG_CODES = {tag: code for code, tag in TAG_NAMES.items()}


def to_packet(data):
    packet = ""
    for tag_name, value in data.items():
        # Get the corresponding tag name
        tag = TAG_CODES.get(tag_name, tag_name)

        # Convert the tag, length, and value to strings
        tag_str = tag.rjust(3, "0")
        length_str = str(len(value)).rjust(3, "0")
        value_str = str(value)

        # Append the TLV to the packet
        packet += tag_str + length_str + value_str

    return packet


def from_packet(packet):
    data = {}
    while packet:
        # Extract the tag, length, and value from the packet
        tag = packet[:3].strip()
        length = int(packet[3:6].strip())
        value = packet[6 : 6 + length]

        # Get the corresponding tag name
        tag_name = TAG_NAMES.get(tag, tag)

        # Update the packet to remove the processed TLV
        packet = packet[6 + length :]

        # Store the tag and value in the data dictionary
        data[tag_name] = value

    return data


def parse_print_content(raw_content):
    # Split the string based on "*030" sequence
    tlvs = raw_content.split("*030")

    # Create the result list by adding the first TLV as it is,
    # and prepending "030" to subsequent TLVs
    content_array = []
    content_array.append(tlvs[0])
    content_array = content_array + ["030" + sub_tlv for sub_tlv in tlvs[1:]]
    content = [from_packet(content) for content in content_array]

    return content


def send_data(data):
    response = {}

    # Add date and time
    dt = datetime.datetime.now()
    data["DA"] = dt.strftime("%d%m%Y")
    data["HE"] = dt.strftime("%H%M%S")
    current_app.logger.info(data)

    # Convert the data to the required format
    packet = to_packet(data)
    current_app.logger.info(packet)

    # Convert ctypes ans call the API function
    packet_raw = ctypes.c_char_p(packet.encode("utf-8"))
    result_raw = send_data_raw(packet_raw)
    result_packet = result_raw.decode("utf-8")
    current_app.logger.info(result_packet)

    # Convert the result to dict
    result = from_packet(result_packet)
    current_app.logger.info(result)
    response["data"] = result

    # Check the return status of the request
    if "CR" in result and result["CR"] == "000":
        response["status"] = True
    else:
        response["status"] = False

    # Check if any content needs to be printed
    if "DP" in result:
        response["ticket"] = parse_print_content(result["DP"])
    else:
        response["ticket"] = None

    return response


def do_check_network(check_out_id, sequence_id):
    # Build the data dict
    data = {}
    data["TM"] = "009"
    data["NCAI"] = check_out_id
    data["NS"] = sequence_id

    # Send data through the API
    result = send_data(data)

    # Build custom response
    response = {}
    response["status"] = result["status"]
    response["ticket"] = result["ticket"]
    response["data"] = {}

    return response


def do_payment(
    check_out_id, sequence_id, amount, cancelled_sequence_id, currency_id="504"
):
    # Build the data dict
    data = {}
    data["TM"] = "001"
    data["NCAI"] = check_out_id
    data["NS"] = sequence_id
    data["MT"] = "{:012.0f}".format(amount * 100)
    data["DE"] = currency_id
    data["NSA"] = cancelled_sequence_id

    # Send data through the API
    result = send_data(data)

    # Build custom response
    response = {}
    response["status"] = result["status"]
    response["ticket"] = result["ticket"]
    response["data"] = {}

    if "DE" in result["data"]:
        response["data"]["currency_id"] = result["data"]["DE"]
    if "STAN" in result["data"]:
        response["data"]["stan"] = result["data"]["STAN"]
    if "NCAR" in result["data"]:
        response["data"]["card_id"] = result["data"]["NCAR"]
    if "DAEX" in result["data"]:
        response["data"]["daex"] = result["data"]["DAEX"]

    return response


def do_confirmation(
    check_out_id,
    sequence_id,
    amount,
    cancelled_sequence_id,
    currency_id,
    stan,
    card_id,
    daex,
):
    # Build the data dict
    data = {}
    data["TM"] = "002"
    data["NCAI"] = check_out_id
    data["NS"] = sequence_id
    data["MT"] = "{:012.0f}".format(amount * 100)
    data["DE"] = currency_id
    data["STAN"] = stan
    data["NCAR"] = card_id
    data["DAEX"] = daex

    # Send data through the API
    result = send_data(data)

    # Build custom response
    response = {}
    response["status"] = result["status"]
    response["ticket"] = result["ticket"]
    response["data"] = {}

    return response


def do_get_ticket(data):
    # Send data through the API
    result = send_data(data)

    return result
