package pkg

import (
	"fmt"
	"net/http"
	"regexp"
	"strconv"
	"strings"
)

func GetVersion() Version {
	return currentVersion
}

func GetLastVersion() Version {
	return lastVersion
}

func GetVersionHTTPHandler() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, GetVersion().String())
	}
}

func init() {
	currentVersion = ParseVersion(version)

	// ignore errors
	// versionFile := filepath.Join(common.DataDir, "version")
	// var lastVersionStr string
	// f, err := os.OpenFile(versionFile, os.O_RDWR|os.O_CREATE, 0o644)
	// if err == nil {
	// 	_, err = fmt.Fscanf(f, "%s", &lastVersionStr)
	// 	lastVersion = ParseVersion(lastVersionStr)
	// }
	// if err != nil && !os.IsNotExist(err) {
	// 	log.Warn().Err(err).Msg("failed to read version file")
	// 	return
	// }
	// if err := f.Truncate(0); err != nil {
	// 	log.Warn().Err(err).Msg("failed to truncate version file")
	// 	return
	// }
	// _, err = f.WriteString(version)
	// if err != nil {
	// 	log.Warn().Err(err).Msg("failed to save version file")
	// 	return
	// }
}

type Version struct{ Generation, Major, Minor int }

func Ver(major, minor, patch int) Version {
	return Version{major, minor, patch}
}

func (v Version) String() string {
	return fmt.Sprintf("v%d.%d.%d", v.Generation, v.Major, v.Minor)
}

func (v Version) MarshalText() ([]byte, error) {
	return []byte(v.String()), nil
}

func (v Version) IsNewerMajorThan(other Version) bool {
	if v.Generation != other.Generation {
		return v.Generation > other.Generation
	}
	return v.Major > other.Major
}

func (v Version) IsEqual(other Version) bool {
	return v.Generation == other.Generation && v.Major == other.Major && v.Minor == other.Minor
}

var (
	version        = "unset"
	currentVersion Version
	lastVersion    Version
)

var versionRegex = regexp.MustCompile(`^v(\d+)\.(\d+)\.(\d+)(\-\w+)?$`)

func ParseVersion(v string) (ver Version) {
	if v == "" {
		return
	}

	if !versionRegex.MatchString(v) { // likely feature branch (e.g. feat/some-feature)
		return
	}

	v = strings.Split(v, "-")[0]
	v = strings.TrimPrefix(v, "v")
	parts := strings.Split(v, ".")
	if len(parts) != 3 {
		return
	}
	gen, err := strconv.Atoi(parts[0])
	if err != nil {
		return
	}
	major, err := strconv.Atoi(parts[1])
	if err != nil {
		return
	}
	minor, err := strconv.Atoi(parts[2])
	if err != nil {
		return
	}
	return Ver(gen, major, minor)
}
