package common

import (
	"context"
	"fmt"
	"math/rand"
	"net"
	"time"

	"github.com/libp2p/go-libp2p/core/host"
	pp "github.com/libp2p/go-libp2p/core/peer"
	"github.com/multiformats/go-multiaddr"
)

func PeerIsAlive(h host.Host, ad pp.AddrInfo) bool {
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	err := h.Connect(ctx, ad)
	return err == nil
}

func ExtractIP(addr string) (net.IP, error) {
	ma, err := multiaddr.NewMultiaddr(addr)
	if err != nil {
		return nil, err
	}
	ipStr, err := ma.ValueForProtocol(multiaddr.P_IP4)
	if err != nil {
		ipStr, err = ma.ValueForProtocol(multiaddr.P_IP6)
		if err != nil {
			return nil, err
		}
	}
	ip := net.ParseIP(ipStr)
	if ip == nil {
		return nil, fmt.Errorf("invalid IP: %s", ipStr)
	}
	return ip, nil
}

func GetIndexer(addrOrId string) *pp.AddrInfo {
	return Indexers.GetAddr(addrOrId)
}

func GetIndexersIDs() []pp.ID {
	return Indexers.GetAddrIDs()
}

func GetIndexersStr() []string {
	return Indexers.GetAddrsStr()
}

func GetIndexers() []*pp.AddrInfo {
	entries := Indexers.GetAddrs()
	result := make([]*pp.AddrInfo, 0, len(entries))
	for _, e := range entries {
		result = append(result, e.Info)
	}
	return result
}

func Shuffle[T any](slice []T) []T {
	rand.Shuffle(len(slice), func(i, j int) {
		slice[i], slice[j] = slice[j], slice[i]
	})
	return slice
}
