//! Signer implementation for Altius transactions

use crate::Result;
use crate::transaction::{Signer as SignerTrait, Signature as TxSignature};
use alloy_primitives::{Address, B256, keccak256};
use rand::RngCore;

/// A transaction signer
#[derive(Debug)]
pub struct Signer {
    private_key: [u8; 32],
}

impl SignerTrait for Signer {
    fn sign_hash(&self, _hash: &B256) -> std::result::Result<TxSignature, Box<dyn std::error::Error>> {
        // Simplified signing - in production use proper ECDSA
        // For now, use a placeholder that returns valid-looking values
        Ok(TxSignature::new(
            B256::from_slice(&self.private_key),
            B256::from_slice(&keccak256(&self.private_key)[..32]),
            0, // y_parity = 0
        ))
    }

    fn address(&self) -> Address {
        let hash = keccak256(&self.private_key);
        Address::from_slice(&hash[12..32])
    }
}

impl Signer {
    /// Create a signer from a private key hex string
    pub fn from_private_key(private_key: &str) -> Result<Self> {
        let key = private_key.trim_start_matches("0x");
        let bytes = hex::decode(key).map_err(|e| crate::Error::InvalidHex(e.to_string()))?;

        if bytes.len() != 32 {
            return Err(crate::Error::InvalidPrivateKey("private key must be 32 bytes".into()));
        }

        let mut private_key = [0u8; 32];
        private_key.copy_from_slice(&bytes);

        Ok(Self { private_key })
    }
}

/// A wallet with address and optional private key
#[derive(Debug, Clone)]
pub struct Wallet {
    pub address: String,
    pub private_key: Option<String>,
}

impl Wallet {
    pub fn generate() -> Result<Self> {
        let mut key = [0u8; 32];
        rand::thread_rng().fill_bytes(&mut key);

        let signer = Signer::from_private_key(&hex::encode(key))?;
        Ok(Self {
            address: signer.address().to_string(),
            private_key: Some(format!("0x{}", hex::encode(key))),
        })
    }

    pub fn from_private_key(private_key: &str) -> Result<Self> {
        let signer = Signer::from_private_key(private_key)?;
        Ok(Self {
            address: signer.address().to_string(),
            private_key: Some(private_key.to_string()),
        })
    }
}

/// Generate a new private key
pub fn generate_private_key() -> String {
    let mut key = [0u8; 32];
    rand::thread_rng().fill_bytes(&mut key);
    format!("0x{}", hex::encode(key))
}

/// Convert private key to address
pub fn private_key_to_address(private_key: &str) -> Result<String> {
    let signer = Signer::from_private_key(private_key)?;
    Ok(signer.address().to_string())
}
