// Minimal provider abstraction for EVM JSON-RPC
// Uses ethers-core for types and signing
// Uses gloo-net (WASM) or reqwest (native) for HTTP
use std::error::Error;
use ethers_core::types::{U256, Address, Bytes};
use rlp::RlpStream;

/// Send a JSON-RPC POST request to an EVM node.
pub async fn send_rpc(url: &str, body: &str) -> Result<String, Box<dyn Error>> {
    #[cfg(target_arch = "wasm32")]
    {
        use gloo_net::http::Request;
        let resp = Request::post(url)
            .header("content-type", "application/json")
            .body(body)?
            .send()
            .await?;
        Ok(resp.text().await?)
    }
    #[cfg(not(target_arch = "wasm32"))]
    {
        let client = reqwest::Client::new();
        let resp = client
            .post(url)
            .header("content-type", "application/json")
            .body(body.to_string())
            .send()
            .await?;
        Ok(resp.text().await?)
    }
}
pub struct Transaction {
    pub to: Address,
    pub value: U256,
    pub data: Bytes,
    pub gas: Option<U256>,
    pub gas_price: Option<U256>,
    pub nonce: Option<U256>,
    pub chain_id: Option<u64>,
}

impl Transaction {
    pub fn rlp_encode_unsigned(&self) -> Vec<u8> {
        let mut s = RlpStream::new_list(9);
        s.append(&self.nonce);
        s.append(&self.gas_price);
        s.append(&self.gas);
        s.append(&self.to);
        s.append(&self.value);
        s.append(&self.data.to_vec());
        s.append(&self.chain_id);
        s.append(&0u8);
        s.append(&0u8);
        s.out().to_vec()
    }
}

/// Helper to parse a 65-byte secp256k1 signature into (r, s, v) for EVM.
/// Assumes signature is [r (32 bytes) | s (32 bytes) | v (1 byte)]
pub fn parse_signature_rs_v(sig: &[u8], chain_id: u64) -> Option<(U256, U256, u64)> {
    if sig.len() != 65 {
        return None;
    }
    let mut r_bytes = [0u8; 32];
    r_bytes.copy_from_slice(&sig[0..32]);
    let r = U256::from_big_endian(&r_bytes);
    let mut s_bytes = [0u8; 32];
    s_bytes.copy_from_slice(&sig[32..64]);
    let s = U256::from_big_endian(&s_bytes);
    let mut v = sig[64] as u64;
    // EIP-155: v = recid + 35 + chain_id * 2
    if v < 27 { v += 27; }
    v = v + chain_id * 2 + 8;
    Some((r, s, v))
}

// Example usage:
// let (r, s, v) = parse_signature_rs_v(&signature, tx.chain_id).unwrap();
// Use these for EVM transaction serialization.

/// Query the balance of an Ethereum address using eth_getBalance
pub async fn get_balance(url: &str, address: Address) -> Result<U256, Box<dyn std::error::Error>> {
    use serde_json::json;
    let body = json!({
        "jsonrpc": "2.0",
        "method": "eth_getBalance",
        "params": [format!("0x{:x}", address), "latest"],
        "id": 1
    }).to_string();
    let resp = send_rpc(url, &body).await?;
    let v: serde_json::Value = serde_json::from_str(&resp)?;
    let hex = v["result"].as_str().ok_or("No result field in RPC response")?;
    let balance = U256::from_str_radix(hex.trim_start_matches("0x"), 16)?;
    Ok(balance)
}


