package transactions

import (
	"crypto/ecdsa"
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"errors"
	"fmt"
	"math/big"
)

// IsValid realiza validações na transação: assinatura, saldo e nonce.
func (tx *Transaction) IsValid(pubKey *ecdsa.PublicKey, balance float64, currentNonce uint64) error {
	if tx.IsZero() {
		return errors.New("transação malformada: campos obrigatórios ausentes")
	}

	if tx.Value+float64(tx.Gas) > balance {
		return fmt.Errorf("saldo insuficiente: necessário %.2f, disponível %.2f", tx.Value+float64(tx.Gas), balance)
	}

	if tx.Nonce != currentNonce {
		return fmt.Errorf("nonce inválido: esperado %d, recebido %d", currentNonce, tx.Nonce)
	}

	r, s, err := parseSignature(tx.Signature)
	if err != nil {
		return fmt.Errorf("erro ao parsear assinatura: %v", err)
	}

	hash := sha256.Sum256([]byte(fmt.Sprintf("%s:%s:%f:%d:%d",
		tx.From, tx.To, tx.Value, tx.Nonce, tx.Gas)))

	if !ecdsa.Verify(pubKey, hash[:], r, s) {
		return errors.New("assinatura inválida")
	}

	return nil
}

// parseSignature converte a assinatura hex (formato r||s) em *big.Int.
func parseSignature(sig string) (*big.Int, *big.Int, error) {
	bytes, err := hex.DecodeString(sig)
	if err != nil {
		return nil, nil, err
	}
	if len(bytes) != 64 {
		return nil, nil, errors.New("assinatura deve ter 64 bytes (r||s)")
	}
	r := new(big.Int).SetBytes(bytes[:32])
	s := new(big.Int).SetBytes(bytes[32:])
	return r, s, nil
}

// GenerateSignature é uma função auxiliar (para testes): assina tx com chave privada.
func (tx *Transaction) GenerateSignature(priv *ecdsa.PrivateKey) string {
	hash := sha256.Sum256([]byte(fmt.Sprintf("%s:%s:%f:%d:%d",
		tx.From, tx.To, tx.Value, tx.Nonce, tx.Gas)))

	r, s, _ := ecdsa.Sign(rand.Reader, priv, hash[:])
	return fmt.Sprintf("%064x%064x", r, s)
}