"""zg_storage.evm module."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Optional

from web3 import Web3
from web3.types import TxParams


@dataclass
class EvmClient:
    """Lightweight EVM RPC wrapper.

    Purpose:
        Build, sign, and send transactions for contract interactions.
    Notes:
        Uses `web3` under the hood and manages a single account."""

    rpc_url: str
    private_key: str

    def __post_init__(self) -> None:
        """Initialize Web3 client and derive the sender account."""
        self.w3 = Web3(Web3.HTTPProvider(self.rpc_url))
        self.account = self.w3.eth.account.from_key(self.private_key)

    def address(self) -> str:
        """Return the sender address derived from the private key."""
        return self.account.address

    def build_tx(
        self,
        to: str,
        data: bytes,
        value: int = 0,
        gas: Optional[int] = None,
        gas_price: Optional[int] = None,
        nonce: Optional[int] = None,
        chain_id: Optional[int] = None,
    ) -> TxParams:
        """Build a transaction dict with optional gas and nonce fields."""
        if nonce is None:
            nonce = self.w3.eth.get_transaction_count(self.account.address)
        if chain_id is None:
            chain_id = self.w3.eth.chain_id
        tx: TxParams = {
            "to": to,
            "data": data,
            "value": value,
            "nonce": nonce,
            "chainId": chain_id,
        }
        if gas is not None:
            tx["gas"] = gas
        if gas_price is not None:
            tx["gasPrice"] = gas_price
        return tx

    def sign_and_send(self, tx: TxParams) -> str:
        """Sign and broadcast a transaction, returning its hash."""
        signed = self.account.sign_transaction(tx)
        raw_tx = getattr(signed, "rawTransaction", None)
        if raw_tx is None:
            raw_tx = signed.raw_transaction
        tx_hash = self.w3.eth.send_raw_transaction(raw_tx)
        return tx_hash.hex()
