"""Optional crypto helpers for payload verification and decryption."""

from __future__ import annotations

import json

from .errors import CryptoNotAvailableError


def _normalize_hex(value: str) -> str:
    return value.removeprefix("0x")


def canonical_serialize(data: dict) -> bytes:
    """Deterministic JSON encoding used for hashing."""
    return json.dumps(data, sort_keys=True, separators=(",", ":")).encode()


def verify_response_hash(ipfs_payload: dict, on_chain_hash: str) -> bool:
    """Verify that payload hash matches on-chain response hash."""
    try:
        from web3 import Web3
    except Exception as exc:
        raise CryptoNotAvailableError(
            "web3 is required for verify_response_hash. Install with [crypto]."
        ) from exc

    computed = Web3.keccak(canonical_serialize(ipfs_payload)).hex()
    return _normalize_hex(computed).lower() == _normalize_hex(on_chain_hash).lower()


def decrypt_findings(encrypted_payload: dict, private_key_hex: str) -> dict:
    """Decrypt findings payload using a secp256k1 private key."""
    try:
        import ecies
    except Exception as exc:
        raise CryptoNotAvailableError(
            "eciespy is required for decrypt_findings. Install with [crypto]."
        ) from exc

    encrypted_section = encrypted_payload.get("encrypted", encrypted_payload)
    ciphertext_hex = encrypted_section.get("ciphertext")
    if not isinstance(ciphertext_hex, str):
        raise ValueError("encrypted payload is missing a hex ciphertext field")

    ciphertext = bytes.fromhex(_normalize_hex(ciphertext_hex))
    plaintext = ecies.decrypt(_normalize_hex(private_key_hex), ciphertext)
    return json.loads(plaintext)
