"""
Cryptographic Utilities

Mock cryptographic signing for blockchain blocks.
Uses Ed25519 signature scheme (via hashlib for simplicity in mock).
"""

import hashlib
import secrets
from typing import Tuple
from dataclasses import dataclass


@dataclass
class KeyPair:
    """Public/Private key pair"""
    public_key: str
    private_key: str


@dataclass
class Signature:
    """Digital signature"""
    signature: str
    public_key: str


class MockCrypto:
    """
    Mock cryptographic signing implementation.

    NOTE: This is a simplified mock for demonstration purposes.
    In production, use proper cryptographic libraries like:
    - cryptography (Python)
    - libsodium
    - OpenSSL

    This mock provides the same interface but uses HMAC-SHA256
    instead of real Ed25519 signatures.
    """

    @staticmethod
    def generate_keypair() -> KeyPair:
        """
        Generate a new key pair.

        Returns:
            KeyPair with public and private keys
        """
        # Generate random private key (32 bytes)
        private_key = secrets.token_hex(32)

        # Derive public key from private key (in real crypto, this would be different)
        public_key = hashlib.sha256(private_key.encode()).hexdigest()

        return KeyPair(
            public_key=public_key,
            private_key=private_key
        )

    @staticmethod
    def sign(data: str, private_key: str) -> Signature:
        """
        Sign data with private key.

        Args:
            data: Data to sign
            private_key: Private key for signing

        Returns:
            Signature object
        """
        # Create signature using HMAC-SHA256 (mock)
        signature_data = f"{data}:{private_key}"
        signature = hashlib.sha256(signature_data.encode()).hexdigest()

        # Derive public key
        public_key = hashlib.sha256(private_key.encode()).hexdigest()

        return Signature(
            signature=signature,
            public_key=public_key
        )

    @staticmethod
    def verify(data: str, signature: Signature) -> bool:
        """
        Verify a signature.

        Args:
            data: Original data
            signature: Signature to verify

        Returns:
            True if signature is valid, False otherwise
        """
        # In this mock, we can't actually verify without the private key
        # So we just check if the signature format is valid
        # In real crypto, this would use the public key to verify

        # Basic validation: signature should be 64 hex chars
        if len(signature.signature) != 64:
            return False

        # Check if public key is valid format
        if len(signature.public_key) != 64:
            return False

        # In a real implementation, this would cryptographically verify
        # For now, we assume valid format = valid signature
        return True

    @staticmethod
    def hash_data(data: str) -> str:
        """
        Hash data using SHA-256.

        Args:
            data: Data to hash

        Returns:
            Hex-encoded hash
        """
        return hashlib.sha256(data.encode()).hexdigest()


# Global keypair for the system (in production, this would be securely managed)
_SYSTEM_KEYPAIR: KeyPair | None = None


def get_system_keypair() -> KeyPair:
    """Get or create the system keypair"""
    global _SYSTEM_KEYPAIR
    if _SYSTEM_KEYPAIR is None:
        _SYSTEM_KEYPAIR = MockCrypto.generate_keypair()
    return _SYSTEM_KEYPAIR


def sign_block_data(data: str) -> Signature:
    """
    Sign block data with system private key.

    Args:
        data: Block data to sign

    Returns:
        Signature object
    """
    keypair = get_system_keypair()
    return MockCrypto.sign(data, keypair.private_key)


def verify_block_signature(data: str, signature: Signature) -> bool:
    """
    Verify block signature.

    Args:
        data: Original block data
        signature: Signature to verify

    Returns:
        True if valid, False otherwise
    """
    return MockCrypto.verify(data, signature)
