import secrets
from typing import Optional

from ...shared.secrets import PRIVATE_KEY_ENC_KEY, PRIVATE_KEY_ENC_PASSWORD_KEY
from ...shared.secrets import decrypt_private_key, encrypt_private_key, init_env_file, set_env_file


COPY_WALLET_ADDRESS_KEY = "1M_TRADE_COPY_WALLET_ADDRESS"
COPY_PRIVATE_KEY_ENC_KEY = "1M_TRADE_COPY_PRIVATE_KEY_ENC"
COPY_PRIVATE_KEY_ENC_PASSWORD_KEY = "1M_TRADE_COPY_PK_ENC_PASSWORD"


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)}. "
            "请确认私钥是完整的 0x + 64 位 hex。"
        )
    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 resolve_copytrade_plain_private_key_from_env_file(env: dict[str, str]) -> str:
    """
    Resolve copytrade private key (encrypted at rest) with fallback to trade keys.

    Priority:
    1) 1M_TRADE_COPY_PRIVATE_KEY_ENC + 1M_TRADE_COPY_PK_ENC_PASSWORD
    2) HYPERLIQUID_PRIVATE_KEY_ENC + HYPERLIQUID_PK_ENC_PASSWORD
    """

    enc = (env.get(COPY_PRIVATE_KEY_ENC_KEY) or "").strip()
    pwd = (env.get(COPY_PRIVATE_KEY_ENC_PASSWORD_KEY) or "").strip()
    if enc and pwd:
        return decrypt_private_key(enc, pwd)

    # fallback to trade wallet fields
    enc2 = (env.get(PRIVATE_KEY_ENC_KEY) or "").strip()
    pwd2 = (env.get(PRIVATE_KEY_ENC_PASSWORD_KEY) or "").strip()
    if not enc2:
        raise ValueError(f"{COPY_PRIVATE_KEY_ENC_KEY} not found and {PRIVATE_KEY_ENC_KEY} not found")
    if not pwd2:
        raise ValueError(f"{COPY_PRIVATE_KEY_ENC_PASSWORD_KEY} not found and {PRIVATE_KEY_ENC_PASSWORD_KEY} not found")
    return decrypt_private_key(enc2, pwd2)


def resolve_copytrade_wallet_address_from_env_file(env: dict[str, str], *, derived: str | None) -> str | None:
    """
    Resolve copytrade wallet address with fallback to trade keys, and then derived address.
    """

    addr = (env.get(COPY_WALLET_ADDRESS_KEY) or "").strip() or None
    if addr:
        return addr
    addr2 = (env.get("HYPERLIQUID_WALLET_ADDRESS") or "").strip() or None
    if addr2:
        return addr2
    return derived


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

    Writes to the shared OpenClaw state `.env`, but uses copytrade-specific keys:
    - 1M_TRADE_COPY_WALLET_ADDRESS
    - 1M_TRADE_COPY_PRIVATE_KEY_ENC
    - 1M_TRADE_COPY_PK_ENC_PASSWORD

    If you don't set these keys, copytrade will fall back to trade wallet keys.
    """

    env = 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 not addr:
        addr = derived_address
    else:
        if not addr.startswith("0x"):
            addr = "0x" + addr

    enc_password = secrets.token_bytes(32).hex()
    env[COPY_WALLET_ADDRESS_KEY] = addr
    env[COPY_PRIVATE_KEY_ENC_PASSWORD_KEY] = enc_password
    env[COPY_PRIVATE_KEY_ENC_KEY] = encrypt_private_key(pk, enc_password)
    set_env_file(env)

    return addr


__all__ = [
    "COPY_WALLET_ADDRESS_KEY",
    "COPY_PRIVATE_KEY_ENC_KEY",
    "COPY_PRIVATE_KEY_ENC_PASSWORD_KEY",
    "init_wallet",
    "resolve_copytrade_plain_private_key_from_env_file",
    "resolve_copytrade_wallet_address_from_env_file",
]

