package debug

import (
	rdebug "runtime/debug"
	"strings"

	"github.com/blang/semver/v4"
)

var biFunc func() (*rdebug.BuildInfo, bool) = rdebug.ReadBuildInfo

// ModuleVersion returns the version of the named module.
// It reads the build info and parses the version of the requested module.
func ModuleVersion(m string) semver.Version {
	bi, ok := biFunc()
	if !ok || bi == nil {
		Log("Failed to read build info")

		return semver.Version{}
	}

	// special case for gopass
	if m == "github.com/gopasspw/gopass" || strings.HasPrefix(m, "github.com/gopasspw/gopass/") {
		sv, err := semver.Parse(strings.TrimPrefix(bi.Main.Version, "v"))
		if err == nil {
			return sv
		}
		Log("Failed to parse version %q for %q (gopass): %s", bi.Main.Version, m, err)
	}

	for _, dep := range bi.Deps {
		// We might be asking for a package that is part of a module
		// but not the module itself.
		if !strings.HasPrefix(m, dep.Path) {
			continue
		}

		sv, err := semver.Parse(strings.TrimPrefix(dep.Version, "v"))
		if err != nil {
			Log("Failed to parse version %q for %q: %s", dep.Version, dep.Path, err)

			if dep.Version == "" {
				return semver.Version{}
			}

			// remove invalid characters
			dv := strings.Trim(strings.TrimPrefix(dep.Version, "v"), "()")

			return semver.Version{
				Build: []string{dv},
			}
		}

		return sv
	}

	Log("no module %s found. Modules: %v", m, paths(bi.Deps))

	return semver.Version{}
}

func paths(mods []*rdebug.Module) []string {
	out := make([]string, 0, len(mods))
	for _, m := range mods {
		out = append(out, m.Path)
	}

	return out
}
