"""
Common RPC definitions and helpers for the ecmind blue client library
"""

import base64
import hashlib
import logging
import os
from random import randint

from ecmind_blue_client.rpc._blue_exception import BlueException
from ecmind_blue_client.rpc._job_error import JobError
from ecmind_blue_client.rpc._job_parameter import (
    JobParameter,
    JobParameterTypes,
    JobValueT,
    JobValueTypes,
)
from ecmind_blue_client.rpc._job_request_file import (
    JobRequestFile,
    JobRequestFileFromBytes,
    JobRequestFileFromPath,
    JobRequestFileFromReader,
)
from ecmind_blue_client.rpc._job_response_file import (
    JobResponseFile,
    JobResponseFileType,
)
from ecmind_blue_client.rpc._job_result import JobResult
from ecmind_blue_client.rpc._jobs import Jobs
from ecmind_blue_client.rpc._rpc_connection import RpcConnection

__all__ = [
    "JobError",
    "BlueException",
    "JobParameter",
    "JobParameterTypes",
    "JobValueT",
    "JobValueTypes",
    "JobRequestFile",
    "JobRequestFileFromBytes",
    "JobRequestFileFromPath",
    "JobRequestFileFromReader",
    "JobResponseFile",
    "JobResponseFileType",
    "JobResult",
    "Jobs",
    "RpcConnection",
    "password_reveal",
    "password_encrypt",
    "DEFAULT_CA_DATA",
]

logger = logging.getLogger(__name__)


def password_encrypt(password: str) -> str:
    """
    Encrypt a plain-text password using the proprietary Blue obfuscation scheme.

    The algorithm encodes each character as a three-octal-digit value at a random
    offset within a random-noise string, producing a printable ASCII result.
    Because random padding is used, two calls with the same password yield
    different ciphertext strings. The result is reversible only by the Blue server.

    Args:
        password (str): The plain-text password to encrypt. Must not be empty.

    Returns:
        str: The obfuscated, printable ASCII ciphertext.

    Raises:
        ValueError: If ``password`` is an empty string.
    """
    if password == "":
        raise ValueError("Password must not be empty")

    def create_random_char():
        return chr(ord("0") + (randint(0, 32000) % 8))

    plen = len(password)
    nmax = 4 * plen * 2
    ioff = randint(0, 32000) % max(1, nmax - plen * 3 - 3)
    cryptid = chr(ord("A") + plen) + chr(ord("A") + ioff)
    for _ in range(0, ioff):
        cryptid += create_random_char()

    def replace_in_string(i: int, c: str):
        return cryptid[:i] + c + cryptid[i + 1 :]

    for i in range(0, plen):
        j = 2 + ioff + i * 3
        oct_part = ioff + ord(password[i])
        oct_data = f"{oct_part:03o}"
        for k in range(0, 3):
            cryptid = replace_in_string(j + k, oct_data[k])

    for i in range(2 + ioff + 3 * plen, nmax):
        cryptid = replace_in_string(i, create_random_char())

    try:
        cryptid.encode("ascii")
        return cryptid
    except ValueError as ex:
        logger.debug(ex)
        return password_encrypt(password)


def password_reveal(s: str, k: str | None = None) -> str:
    """
    Decrypt a password that was encrypted with the ``ECMIND_KEY``-based XOR scheme.

    The function base85-decodes ``s`` and XOR-decrypts it using the MD5 hash of
    the key. The key is resolved in the following priority order:

    1. The ``ECMIND_KEY`` environment variable (if set and non-empty).
    2. The ``k`` argument.
    3. An empty string (no key).

    If decoding fails (e.g. ``s`` is not base85-encoded), the original string
    ``s`` is returned unchanged.

    Args:
        s (str): The base85-encoded, XOR-encrypted password string.
        k (str | None): Optional fallback key when ``ECMIND_KEY`` is not set.

    Returns:
        str: The decrypted plain-text password, or ``s`` unchanged if decoding fails.
    """
    k = hashlib.md5(os.environ.get("ECMIND_KEY", k or "").encode()).hexdigest()
    try:
        d: list[str] = []
        r = base64.b85decode(s).decode()
        for i, char in enumerate(r):
            c = k[i % len(k)]
            b = chr((256 + ord(char) - ord(c)) % 256)
            d.append(b)
        return "".join(d)
    except UnicodeDecodeError:
        return s


# Old and current blue server certificate for validation
DEFAULT_CA_DATA = """-----BEGIN CERTIFICATE-----
MIIF/TCCA+WgAwIBAgIBFzANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCREUx
DzANBgNVBAgMBkJlcmxpbjEPMA0GA1UEBwwGQmVybGluMRgwFgYDVQQKDA9PUFRJ
TUFMIFNZU1RFTVMxFTATBgNVBAsMDEJsdWUgQ2VudHJhbDEhMB8GA1UEAwwYQmx1
ZSBDZW50cmFsIGltZXJtZWRpYXRlMB4XDTE5MDEyODE3NDIwNFoXDTI3MDQxNjE3
NDIwNFowdDELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0GA1UEBwwG
QmVybGluMRgwFgYDVQQKDA9PUFRJTUFMIFNZU1RFTVMxFTATBgNVBAsMDEJsdWUg
Q2VudHJhbDESMBAGA1UEAwwJQXBwU2VydmVyMIICIjANBgkqhkiG9w0BAQEFAAOC
Ag8AMIICCgKCAgEAxXSPc72aZr1wuLfpZ6Lpu7XQuS4EPImNQccJg+JUxRFhBQa1
Dme+dYLpdA7t5L2f5o00AOMVu5sCncIQ66yxtQe/ZlCUPhL9bBWfj/Yfs89PFQKQ
wCISfdBmtqsY6pEK89qelbnEtCWIjBEzAm5z9p6AOk9iBZvzKSQb9ehNzP2AMtP5
k53b8dXhjKTNM92MNzvO92ETqKUMdauzopSklRVLk6T3DRgJs+wpoKUCVvtXyoF/
feilzPabku0+Tomui8hjrXnlcHo94Gp7dVxMPsxwyzKbYLRAM6pQ4vhzv+QmAOwS
qgP79MupckGf70DMenHDjntrSw4l10if4q19xo+FJU+lfbGdPOSEMM0M3ttaAZUl
+5HltzmTxhg6djhZV+myLKHMTlPaW76MWlzj2nKSJ63mOb4NF22NSuWSE8X2RRvO
PNOZ3qaIV9a+2ljjPu8Sqmbo/ut7wcrty5ETCp3qZppM2vg8R4JfseTk5Nupfktf
/lthfDMlX79VCou229yaLxAGqJv/WvXiy/zrGPLIrIsiiYv8aeAbxWK+hF3ea90B
byHwKBAKT55RJ8fEqYWkxUdVEO5429UWKiZ0QhWas8NaZ2IokH2wjHfAKjHgVCBX
mXU37lc6g3gNEL1NDPq5x9IxC+pWEx/H094xZ5AgyH4KF8h14uuczYrA8uECAwEA
AaOBiTCBhjAdBgNVHQ4EFgQURyhC1GDxZgQGq+aT8dU15rVmZSYwHwYDVR0jBBgw
FoAUPfCYO8wLyAv/Zl3XOrmZhx9cniswCQYDVR0TBAIwADALBgNVHQ8EBAMCBaAw
LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMA0G
CSqGSIb3DQEBCwUAA4ICAQBwYbo4QKNwzV8Wy3mj9iUMHPp+fb/b1YTU7+wmqCmv
ymyr83pQiuth2nu3y+7QEqHwDX+KJBm3XO1ej7GPZ5tZ6ssOsYQVGA5l7ujrsm/r
aBr3n5cghiuggX2K9lbP8/I9HwvWPOqdtSHqy5ILQgQGR4mnh8zc1zPwIeYSLkeJ
FjTChyx6ZX1p+gKYg+QQ4OzfLDbueTW/4oQrrH+DjvfD9yZnh0DRiL700NpQZxb4
mnSqVS0rjMyLcNxc9M6IcivOqDy490CLcAj1KYjFP7B/Ehf4Po96p+geqDZRRs0v
GfcRG4qaPi6mJ0p5Yf4PWeLN8ZBydg08pf3F4EDKcV+zzWoMq6ywwkUVPe5x+czJ
cwKMIvCogaQRqzEBAuDGEMPkfz/Nl0wEy3zhx8gtVRvv/sjfCyyVm5rAS+ROkVAi
w5njrOhKAGBYnVOfBEiCukCQYXNOP+/Rdi+J4QK81olPFnVpb07ltFhw68Gc+MXZ
QKmed6+PTJak8/Wgqe/7SZtXq8NPElaLax7rfIQIrEgB01ow2PqhHdkQ8w0VKL2Z
wSHyqIw00O/27DxxV1KWZkkNoen9RzY5YzzIknJ+4IaP18hyOfHm4bjrzUGvYumG
WumfghHwh0F3EQEqH/T8vlGOALteuzG8aSNs9CWqtOK5qvQn+B9eUmjldwrVI0hR
NA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
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
sBAN
-----END CERTIFICATE-----
"""
