"""Key derivation: private key → public key → Stacks address.

Uses coincurve for secp256k1 operations and hashlib for hashing.
"""

from __future__ import annotations

import hashlib

from coincurve import PrivateKey

from .c32 import c32_address
from .constants import (
    ADDRESS_VERSION_MAINNET_SINGLE_SIG,
    ADDRESS_VERSION_TESTNET_SINGLE_SIG,
)


def private_key_to_public_key(private_key_hex: str) -> bytes:
    """Derive compressed public key (33 bytes) from a hex private key."""
    key_hex = private_key_hex.removeprefix("0x")
    # Handle keys with compression flag suffix (01)
    if len(key_hex) == 66 and key_hex.endswith("01"):
        key_hex = key_hex[:64]
    pk = PrivateKey(bytes.fromhex(key_hex))
    return pk.public_key.format(compressed=True)


def hash160(data: bytes) -> bytes:
    """Compute RIPEMD160(SHA256(data))."""
    sha = hashlib.sha256(data).digest()
    ripemd = hashlib.new("ripemd160", sha).digest()
    return ripemd


def get_address_version(network: str) -> int:
    """Get address version byte for a network ('mainnet' or 'testnet')."""
    if network == "mainnet":
        return ADDRESS_VERSION_MAINNET_SINGLE_SIG
    return ADDRESS_VERSION_TESTNET_SINGLE_SIG


def public_key_to_address(pubkey: bytes, network: str = "testnet") -> str:
    """Derive Stacks address from compressed public key."""
    h160 = hash160(pubkey)
    version = get_address_version(network)
    return c32_address(version, h160)


def private_key_to_address(private_key_hex: str, network: str = "testnet") -> str:
    """Derive Stacks address from hex private key."""
    pubkey = private_key_to_public_key(private_key_hex)
    return public_key_to_address(pubkey, network)
