"""Ed25519 signing helpers for AMCS/IAP continuity features."""

from __future__ import annotations

import base64
import binascii

from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives.asymmetric.ed25519 import (
    Ed25519PrivateKey,
    Ed25519PublicKey,
)
from cryptography.hazmat.primitives.serialization import (
    Encoding,
    NoEncryption,
    PrivateFormat,
    PublicFormat,
)


def generate_keypair() -> tuple[bytes, bytes]:
    """Generate Ed25519 private/public keypair bytes."""
    private_key = Ed25519PrivateKey.generate()
    public_key = private_key.public_key()
    private_bytes = private_key.private_bytes(
        encoding=Encoding.Raw,
        format=PrivateFormat.Raw,
        encryption_algorithm=NoEncryption(),
    )
    public_bytes = public_key.public_bytes(encoding=Encoding.Raw, format=PublicFormat.Raw)
    return private_bytes, public_bytes


def sign(private_key: bytes, message_bytes: bytes) -> bytes:
    """Sign bytes with an Ed25519 private key (raw 32-byte encoding)."""
    if len(private_key) != 32:
        raise ValueError("Ed25519 private key must be 32 bytes")
    key = Ed25519PrivateKey.from_private_bytes(private_key)
    return key.sign(message_bytes)


def verify(public_key: bytes, message_bytes: bytes, signature_bytes: bytes) -> bool:
    """Verify Ed25519 signature. Returns False on invalid signature."""
    if len(public_key) != 32 or len(signature_bytes) != 64:
        return False
    key = Ed25519PublicKey.from_public_bytes(public_key)
    try:
        key.verify(signature_bytes, message_bytes)
    except (InvalidSignature, ValueError):
        return False
    return True


def b64encode(data: bytes) -> str:
    return base64.b64encode(data).decode("ascii")


def b64decode(data: str) -> bytes:
    try:
        return base64.b64decode(data, validate=True)
    except binascii.Error as exc:
        raise ValueError("invalid base64 input") from exc
