// Copyright (c) 2017-2026 Lethean (https://lt.hn)
//
// Licensed under the European Union Public Licence (EUPL) version 1.2.
// SPDX-License-Identifier: EUPL-1.2

package p2p

import (
	"strconv"
	"strings"
)

const (
	// MinimumRequiredBuildVersionMainnet matches the C++ daemon's mainnet gate.
	MinimumRequiredBuildVersionMainnet uint64 = 601

	// MinimumRequiredBuildVersionTestnet matches the C++ daemon's testnet gate.
	MinimumRequiredBuildVersionTestnet uint64 = 2
)

// MinimumRequiredBuildVersion returns the minimum accepted peer version gate
// for the given network.
//
// Example:
//
//	MinimumRequiredBuildVersion(false) // 601 on mainnet
func MinimumRequiredBuildVersion(isTestnet bool) uint64 {
	if isTestnet {
		return MinimumRequiredBuildVersionTestnet
	}
	return MinimumRequiredBuildVersionMainnet
}

// PeerBuildVersion extracts the numeric major.minor.revision component from a
// daemon client version string.
//
// The daemon formats its version as "major.minor.revision.build[extra]".
// The minimum build gate compares the first three components, so
// "6.0.1.2[go-blockchain]" becomes 601.
func PeerBuildVersion(clientVersion string) (uint64, bool) {
	parts := strings.SplitN(clientVersion, ".", 4)
	if len(parts) < 3 {
		return 0, false
	}

	major, err := strconv.ParseUint(parts[0], 10, 64)
	if err != nil {
		return 0, false
	}
	minor, err := strconv.ParseUint(parts[1], 10, 64)
	if err != nil {
		return 0, false
	}

	revPart := parts[2]
	for i := 0; i < len(revPart); i++ {
		if revPart[i] < '0' || revPart[i] > '9' {
			revPart = revPart[:i]
			break
		}
	}
	if revPart == "" {
		return 0, false
	}

	revision, err := strconv.ParseUint(revPart, 10, 64)
	if err != nil {
		return 0, false
	}

	return major*100 + minor*10 + revision, true
}

// MeetsMinimumBuildVersion reports whether the peer's version is acceptable
// for the given network.
//
// Example:
//
//	MeetsMinimumBuildVersion("6.0.1.2[go-blockchain]", false) // true
func MeetsMinimumBuildVersion(clientVersion string, isTestnet bool) bool {
	buildVersion, ok := PeerBuildVersion(clientVersion)
	if !ok {
		return false
	}
	return buildVersion >= MinimumRequiredBuildVersion(isTestnet)
}
