import secrets
from typing import Optional

from . import secrets as wallet_secrets
from ..shared.secrets import PRIVATE_KEY_ENC_KEY, PRIVATE_KEY_ENC_PASSWORD_KEY


def _normalize_evm_private_key_hex(raw: str) -> str:
    s = str(raw or "").strip()
    if not s:
        raise ValueError("--pri_key is required")
    if s.startswith("0x") or s.startswith("0X"):
        s_hex = s[2:]
    else:
        s_hex = s
    s_hex = s_hex.strip()

    if len(s_hex) != 64:
        raise ValueError(
            f"invalid --pri_key length: expected 64 hex chars (32 bytes), got {len(s_hex)}. "
            "Please make sure the private key is a full 0x + 64 hex chars."
        )
    try:
        int(s_hex, 16)
    except Exception as e:  # noqa: BLE001
        raise ValueError("invalid --pri_key: not valid hex string") from e
    return "0x" + s_hex.lower()


def init_wallet(address: Optional[str], pri_key: str) -> str:
    """
    Initialize wallet from user-provided private key (+ optional address).

    Overwrites ``HYPERLIQUID_WALLET_ADDRESS``, encrypted private key, and encryption
    password in the state ``.env`` if they already exist.
    Uses AES-GCM+scrypt (v1 payload format) for the encrypted key.
    """

    env = wallet_secrets.init_env_file()

    addr = str(address or "").strip()
    pk = _normalize_evm_private_key_hex(pri_key)

    from eth_account import Account

    account = Account.from_key(pk)
    derived_address = account.address

    # If address is omitted, derive from private key.
    if not addr:
        addr = derived_address
    else:
        # If user supplies address, we accept it as-is (no derived-address validation),
        # because user may use a proxy private key.
        if not addr.startswith("0x"):
            addr = "0x" + addr

    enc_password = secrets.token_bytes(32).hex()
    env["HYPERLIQUID_WALLET_ADDRESS"] = addr
    env[PRIVATE_KEY_ENC_PASSWORD_KEY] = enc_password
    env[PRIVATE_KEY_ENC_KEY] = wallet_secrets.encrypt_private_key(pk, enc_password)
    wallet_secrets.set_env_file(env)

    return addr


__all__ = ["init_wallet"]

