package consensus

import (
	"crypto/sha256"
	"encoding/hex"
	"errors"
	"fmt"

	"dejo_node/internal/transactions"
)

// PoSEngine é uma implementação simples e fake de um consenso Proof-of-Stake.
type PoSEngine struct {
	validators []string
}

// NewPoSEngine cria um novo mecanismo de consenso PoS.
func NewPoSEngine(validators []string) *PoSEngine {
	return &PoSEngine{
		validators: validators,
	}
}

// ValidateBlock verifica se o bloco tem dados válidos.
func (p *PoSEngine) ValidateBlock(block *transactions.Block) error {
	if block == nil {
		return errors.New("bloco nulo")
	}
	if block.Index == 0 && block.PrevHash != "" {
		return errors.New("bloco gênese não deve ter PrevHash")
	}
	if len(block.Txns) == 0 {
		return errors.New("bloco sem transações")
	}
	return nil
}

// SelectProposer seleciona pseudo-aleatoriamente um validador com base na altura.
func (p *PoSEngine) SelectProposer(height uint64) (string, error) {
	if len(p.validators) == 0 {
		return "", errors.New("nenhum validador registrado")
	}
	hash := sha256.Sum256([]byte(fmt.Sprintf("%d", height)))
	index := int(hash[0]) % len(p.validators)
	return p.validators[index], nil
}

// FinalizeBlock simula a finalização de bloco assinando seu hash.
func (p *PoSEngine) FinalizeBlock(block *transactions.Block) error {
	hash := sha256.Sum256([]byte(fmt.Sprintf("%d:%s:%d", block.Index, block.PrevHash, len(block.Txns))))
	block.Hash = hex.EncodeToString(hash[:])
	return nil
}