import axios from "axios";
import crypto from "crypto";
import getStorage from "./storage";

const QR_GENERATOR_URL = 'https://api.paylibo.com/paylibo/generator/image';
const COUNTRY_CODE = 'CZ';
const CURRENCY_CODE = 'CZK';
const QR_PIXEL_SIZE = 256;

const storage = getStorage();

/**
 * Převede číslo účtu z BBAN do IBAN. Automaticky dopočítá kontrolní číslice.
 *
 * @param bankAccountNumber číslo účtu ve formátu BBAN (123456-0123456789/0100)
 */
export function convertBbanToIban(bankAccountNumber: string): string {
    // TODO validovat číslo účtu stejně jako na klientovi, pro případ že sem někdo pošle nesmysl
    let prefix: string = '';
    let accountNumber: string = bankAccountNumber;
    if (bankAccountNumber.indexOf('-') >= 0) {
        const split = bankAccountNumber.split('-');
        prefix = split[0];
        accountNumber = split[1];
    }
    prefix = prefix.padStart(6, '0');
    const split = accountNumber.split('/');
    accountNumber = split[0].padStart(10, '0');
    const bankCode = split[1].padStart(4, '0');
    let iban = `${bankCode}${prefix}${accountNumber}${COUNTRY_CODE}00`;
    // Zatím napevno, nemá smysl řešit nic jiného než CZ
    iban = iban.replace('C', '12').replace('Z', '35');
    const remainder = BigInt(iban) % BigInt(97);
    const checkDigits = BigInt(98) - remainder;
    iban = `${COUNTRY_CODE}${checkDigits.toString()}${bankCode}${prefix}${accountNumber}`;
    if (iban.length !== 24) {
        throw Error("Neplatná délka sestaveného IBAN: " + iban.length + ", očekáváno 24");
    }
    return iban;
}

function createStorageKey(customerName: string, id: string): string {
    const nameHash = crypto.createHash('md5').update(customerName).digest('hex');
    return `qr_${nameHash}_${id}`;
}

/**
 * Vygeneruje a uloží obrázek platebního QR kódu do storage (Redis/JSON).
 * Data přežijí redeploy — není třeba persistentní filesystém.
 *
 * @param customerName jméno uživatele, pro kterého je QR kód generován
 * @param bankAccountNumber číslo cílového bankovního účtu ve formátu BBAN
 * @param bankAccountHolder jméno držitele cílového bankovního účtu
 * @param amount částka v Kč
 * @param message zpráva pro příjemce
 * @param id unikátní identifikátor (UUID) tohoto QR kódu
 */
export async function generateQr(customerName: string, bankAccountNumber: string, bankAccountHolder: string, amount: number, message: string, id: string): Promise<void> {
    // Zpráva pro příjemce nesmí dle standardu obsahovat '*' a být delší než 60 znaků
    if (message.indexOf('*') >= 0) {
        message = message.replace(/\*/g, '');
    }
    if (message.length > 60) {
        message = message.substring(0, 60);
    }
    const payload = {
        iban: convertBbanToIban(bankAccountNumber),
        amount,
        currency: CURRENCY_CODE,
        message,
        recipientName: bankAccountHolder,
        branding: false,
        compress: false,
        size: QR_PIXEL_SIZE,
    };
    const response = await axios.get(QR_GENERATOR_URL, { responseType: 'arraybuffer', params: { ...payload } });
    const base64 = Buffer.from(response.data).toString('base64');
    await storage.setData(createStorageKey(customerName, id), base64);
}

/**
 * Vrátí obrázek s QR kódem ze storage.
 *
 * @param customerName jméno uživatele
 * @param id unikátní identifikátor QR kódu
 * @returns data obrázku
 */
export async function getQr(customerName: string, id: string): Promise<Buffer> {
    const base64 = await storage.getData<string>(createStorageKey(customerName, id));
    if (!base64) {
        throw new Error("QR kód nebyl nalezen");
    }
    return Buffer.from(base64, 'base64');
}
