/*******************************************************************************
 * Copyright (c) 2025, Jan Koester jan.koester@gmx.net
 * All rights reserved.
 * * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the <organization> nor the
 * names of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

#include <iostream>
#include <cassert>
#include "../src/crypto/rsa.h"

using namespace netplus;

void test_bigint_addition() {
    // Specify capacity explicitly as size_t
    rsa::bigInt a(static_cast<size_t>(10));
    rsa::bigInt b(static_cast<size_t>(10));
    rsa::bigInt res(static_cast<size_t>(11));

    a.fromUint64(999);
    b.fromUint64(1);

    rsa::add(a, b, res);

    assert(res.equalsUint64(1000));
    std::cout << "[PASS] BigInt Addition\n";
}

void test_bigint_multiplication() {
    rsa::bigInt a(static_cast<size_t>(10));
    rsa::bigInt b(static_cast<size_t>(10));
    rsa::bigInt res(static_cast<size_t>(20));

    a.fromUint64(12);
    b.fromUint64(12);

    rsa::multiply(a, b, res);

    assert(res.equalsUint64(144));
    std::cout << "[PASS] BigInt Multiplication\n";
}

void test_rsa_lifecycle() {
    rsa crypto;
    rsa::bigInt msg(static_cast<size_t>(20));

    msg.fromUint64(42);

    // generateKeys(bits) - 10 bits is very small, usually use 512+ for testing
    crypto.generateKeys(128);

    rsa::bigInt encrypted = crypto.encrypt(msg);
    rsa::bigInt decrypted = crypto.decrypt(encrypted);

    std::cout << "DEBUG: Cipher=0x" << encrypted.toHexString() << std::endl;
    std::cout << "[DEBUG] Decrypted: 0x" << decrypted.toHexString() << std::endl;

    std::cout << "[PASS] RSA Lifecycle (Encrypt/Decrypt)\n";
}

int main() {
    try {
        test_bigint_addition();
        test_bigint_multiplication();
        test_rsa_lifecycle();
        std::cout << "\nAll tests passed successfully!\n";
    } catch (const std::exception& e) {
        std::cerr << "\nTest failed with error: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}
