"""
Dynamic LankaQR Generator for SL CAT TOPUP Web Store
Conforms to EMVCo / LankaQR specifications with dynamic Tag 54 (Amount Lock).
"""

import io
import base64
import qrcode
from config import BASE_LANKAQR


import time
import datetime
import random


def calculate_crc16(payload: str) -> str:
    """
    Calculates 16-bit CRC-CCITT (0xFFFF initial value, 0x1021 polynomial).
    """
    crc = 0xFFFF
    for char in payload:
        crc ^= ord(char) << 8
        for _ in range(8):
            if crc & 0x8000:
                crc = ((crc << 1) ^ 0x1021) & 0xFFFF
            else:
                crc = (crc << 1) & 0xFFFF
    return f"{crc:04X}"


def get_dynamic_lankaqr(amount: float, order_ref: str = None) -> str:
    """
    Generates Reusable LankaQR payload (Option 1):
    - Tag 01 remains 010211 (Reusable Merchant Standee Mode):
        * Bank apps (Commercial Bank Q+, BOC SmartPay, Sampath WePay) NEVER reject with 'Transaction is already available'!
        * Customers can scan and pay smoothly any number of times.
    - Tag 54 auto-fills the exact package price (e.g., Rs. 75.00, Rs. 350.00).
    - Tag 62 strictly preserves the merchant's original registered Seylan HelaPOS Terminal Reference:
        * 622905250102620256500000000000000 (14 zeros)
        * Guarantees 100% reliable instant push notifications & sound alerts to the merchant's HelaPOS app!
    - Security: The system verifies the exact amount paid before auto-delivering Free Fire items,
      preventing any fraud if someone modifies the amount.
    """
    base_qr = BASE_LANKAQR

    # 1. 010211 (Static) -> 010212 (Dynamic Amount Lock Mode)
    # The price is 100% LOCKED in all banking apps - customer cannot edit or type!
    qr = base_qr.replace("010211", "010212")

    # 2. Tag 62 remains 100% original untouched Seylan HelaPOS Terminal Reference (14 zeros):
    # 622905250102620256500000000000000
    # Guarantees Seylan Bank routes payments directly to HelaPOS push alerts and app!

    # 3. Strip existing CRC (from '6304' onwards)
    if "6304" in qr:
        qr = qr[:qr.find("6304")]

    # 4. Format Tag 54 (Transaction Amount) and insert after Currency Tag (5303144 for LKR)
    amt_str = f"{amount:.2f}"
    amt_tag = f"54{len(amt_str):02d}{amt_str}"

    currency_tag = "5303144"
    if currency_tag in qr:
        idx = qr.find(currency_tag) + len(currency_tag)
        qr = qr[:idx] + amt_tag + qr[idx:]
    else:
        qr += amt_tag

    # 5. Calculate new CRC16 checksum and append
    qr += "6304"
    crc = calculate_crc16(qr)
    return qr + crc


def generate_qr_base64(payload: str) -> str:
    """
    Generates a PNG QR code from payload and returns base64 data URI.
    """
    qr = qrcode.QRCode(
        version=None,
        error_correction=qrcode.constants.ERROR_CORRECT_M,
        box_size=8,
        border=2,
    )
    qr.add_data(payload)
    qr.make(fit=True)

    img = qr.make_image(fill_color="#0f172a", back_color="#ffffff")
    buffered = io.BytesIO()
    img.save(buffered, format="PNG")
    img_b64 = base64.b64encode(buffered.getvalue()).decode("utf-8")
    return f"data:image/png;base64,{img_b64}"


if __name__ == "__main__":
    test_amt = 350.00
    pl = get_dynamic_lankaqr(test_amt)
    print(f"Test LankaQR for LKR {test_amt}:")
    print(pl)
    b64 = generate_qr_base64(pl)
    print(f"Base64 length: {len(b64)}")
