"""
Data processors for evaluating and matching raw database values.

This module is responsible for the core extraction, AES decryption,
and text matching logic utilized by the parallel search engine.
"""

from os import getenv
import base64
import hashlib

from cryptography.fernet import Fernet, InvalidToken
from typing import Any
from .utils import normalize_text

try:
    AES_PASSWORD = getenv("AES_PASSWORD")
    if AES_PASSWORD is not None:
        # Derive a URL-safe base64 encoded 32-byte key from the raw password
        AES_KEY = base64.urlsafe_b64encode(
            hashlib.sha256(AES_PASSWORD.encode()).digest()
        )
        FERNET_INSTANCE = Fernet(AES_KEY)
    else:
        raise ValueError("AES_PASSWORD not found in environment variables.")
except Exception as e:
    raise RuntimeError(f"Failed to initialize AES encryption key: {e}")


def process_values(encrypted_values_list: tuple[Any, ...], search: str) -> int | None:
    """
    Decrypts and inspects a single row of raw database values obtained via `.values_list()`.

    Args:
        encrypted_values_list (tuple[Any, ...]): A tuple containing the primary key at index 0,
            followed by the raw (potentially encrypted) field values to be inspected.
        search (str): The normalized search string to match against the decrypted values.

    Returns:
        int | None: The primary key (integer) if a text match is found in any field,
        otherwise returns None.

    Raises:
        Exception: If a cryptographic error or decoding failure occurs during processing.
    """
    for encrypted_value in encrypted_values_list:
        try:
            # Handle encrypted bytes and plain string representations
            if isinstance(encrypted_value, bytes):
                value_to_check = FERNET_INSTANCE.decrypt(encrypted_value).decode()
            else:
                value_to_check = str(encrypted_value)

            # Perform a substring search against the normalized text
            if search in normalize_text(value_to_check):
                return int(
                    encrypted_values_list[0]
                )  # Return the primary key immediately upon match

        except (InvalidToken, ValueError, TypeError) as e:
            raise Exception(f"Error decrypting database payload: {e}")

    return None
