<?php

/**
 * Generate a random 25-character site ID consisting of alphanumeric characters.
 *
 * @return string
 */
function sc_generate_site_id()
{
    $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $id = '';
    for ($i = 0; $i < 25; $i++) {
        $id .= $chars[random_int(0, strlen($chars) - 1)];
    }
    return $id;
}

/**
 * Generate a random 25-character registration ID consisting of alphanumeric characters.
 *
 * @return string
 */
function sc_generate_registration_id()
{
    $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $id = '';
    for ($i = 0; $i < 25; $i++) {
        $id .= $chars[random_int(0, strlen($chars) - 1)];
    }
    return $id;
}

/**
 * Generate a random 25-character registration ID consisting of alphanumeric characters.
 *
 * @return string
 */
function sc_generate_site_token()
{
    $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $id = '';
    for ($i = 0; $i < 25; $i++) {
        $id .= $chars[random_int(0, strlen($chars) - 1)];
    }
    return $id;
}

/**
 * Generates an RSA keypair, encrypts the private key using AUTH_KEY, and returns both keys.
 *
 * @return array
 *   - success: bool
 *   - public_key: string (PEM-encoded public key)
 *   - private_key_encrypted: string (base64-encoded encrypted private key)
 *   - iv: string (base64-encoded initialization vector)
 */
function sc_generate_keypair()
{
    $config = [
      'private_key_bits' => 2048,
      'private_key_type' => \OPENSSL_KEYTYPE_RSA,
    ];

    $res = openssl_pkey_new($config);
    if (!$res) {
        return ['success' => false, 'message' => 'Key generation failed: ' . openssl_error_string()];
    }

    openssl_pkey_export($res, $private_key);
    $public_key_details = openssl_pkey_get_details($res);
    $public_key = $public_key_details['key'];

    $encryption_key = hash('sha256', AUTH_KEY, true);
    $iv = openssl_random_pseudo_bytes(16);

    $private_key_encrypted = openssl_encrypt(
        $private_key,
        'aes-256-cbc',
        $encryption_key,
        \OPENSSL_RAW_DATA,
        $iv
    );

    return [
      'success' => true,
      'public_key' => $public_key,
      'private_key_encrypted' => base64_encode($private_key_encrypted),
      'iv' => base64_encode($iv),
    ];
}

/**
 * Decrypts the encrypted private key using AUTH_KEY and the provided IV.
 *
 * @param string $encrypted_private_key Base64-encoded encrypted private key
 * @param string $iv Base64-encoded initialization vector
 * @return string Decrypted private key (PEM format)
 */
function sc_decrypt_private_key($encrypted_private_key, $iv)
{
    $encryption_key = hash('sha256', AUTH_KEY, true);
    $encrypted_private_key = base64_decode($encrypted_private_key);

    $private_key = openssl_decrypt(
        $encrypted_private_key,
        'aes-256-cbc',
        $encryption_key,
        \OPENSSL_RAW_DATA,
        base64_decode($iv)
    );

    return $private_key;
}

/**
 * Decrypts encrypted data using the stored private key.
 *
 * @param string $encrypted_data Base64-encoded encrypted data
 * @return string Decrypted plaintext data
 * @throws Exception if decryption fails or private key is invalid
 */
function sc_decrypt_data($encrypted_data)
{
    $encrypted_private_key = get_option('sc_private_key');
    $iv = get_option('sc_private_key_iv');
    $private_key = sc_decrypt_private_key($encrypted_private_key, $iv);
    $private_key_resource = openssl_pkey_get_private($private_key);

    if ($private_key_resource === false) {
        throw new Exception('Invalid private key.');
    }

    $encrypted_data = base64_decode($encrypted_data);
    $decrypted_data = '';

    $success = openssl_private_decrypt($encrypted_data, $decrypted_data, $private_key_resource);

    if (!$success) {
        throw new Exception('Decryption failed.');
    }

    openssl_free_key($private_key_resource);

    return $decrypted_data;
}

/**
 * Encrypts data using the stored public key.
 *
 * @param string $data Plaintext data to encrypt
 * @return string Base64-encoded encrypted data
 * @throws Exception if encryption fails or public key is not found
 */
function sc_encrypt_data($data)
{
    $public_key = get_option('sc_public_key');
    if (!$public_key) {
        throw new Exception('Public key not found.');
    }

    $public_key_resource = openssl_pkey_get_public($public_key);
    if ($public_key_resource === false) {
        throw new Exception('Invalid public key.');
    }

    $encrypted = '';
    $success = openssl_public_encrypt($data, $encrypted, $public_key_resource);

    if (!$success) {
        throw new Exception('Encryption failed.');
    }

    openssl_free_key($public_key_resource);

    return base64_encode($encrypted);
}
