package consensus

import (
	"dejo_node/internal/staking"
	"sort"
)

type Validator struct {
	Address string
	Stake   uint64
}

type ValidatorSet struct {
	Validators []Validator
	IndexMap   map[string]int
}

func NewValidatorSetFromStaking(store *staking.StakingStore, minStake uint64) *ValidatorSet {
	vals := []Validator{}
	storeSnapshot := store.Snapshot()
	for addr, entry := range storeSnapshot {
		if entry.Amount >= minStake {
			vals = append(vals, Validator{Address: addr, Stake: entry.Amount})
		}
	}

	sort.Slice(vals, func(i, j int) bool {
		return vals[i].Stake > vals[j].Stake
	})
	idx := make(map[string]int)
	for i, v := range vals {
		idx[v.Address] = i
	}
	return &ValidatorSet{Validators: vals, IndexMap: idx}
}

func (vs *ValidatorSet) SelectProposer(height uint64) *Validator {
	if len(vs.Validators) == 0 {
		return nil
	}
	index := int(height % uint64(len(vs.Validators)))
	return &vs.Validators[index]
}

func (vs *ValidatorSet) IsValidator(address string) bool {
	_, ok := vs.IndexMap[address]
	return ok
}

func (vs *ValidatorSet) TotalStake() uint64 {
	sum := uint64(0)
	for _, v := range vs.Validators {
		sum += v.Stake
	}
	return sum
}

func (vs *ValidatorSet) ValidatorByAddress(addr string) (Validator, bool) {
	i, ok := vs.IndexMap[addr]
	if !ok {
		return Validator{}, false
	}
	return vs.Validators[i], true
}