package versionimp

import (
	"bytes"
	"fmt"
	"regexp"
	"runtime"
	"strings"
	"text/template"

	"github.com/tech/sendico/pkg/version"
)

// versionInfoTmpl contains the template used by Info.
var versionInfoTmpl = `
{{.program}}, version {{.version}} (branch: {{.branch}}, revision: {{.revision}})
  build user:       {{.buildUser}}
  build date:       {{.buildDate}}
  go version:       {{.goVersion}}
  go OS:            {{.goOS}}
  go Architecture:  {{.goArch}}
`

func parseVersion(input, revision string) (string, string) {
	var version string

	// Regular expression to match different version formats
	re := regexp.MustCompile(`^v?(\d+\.\d+\.\d+)(?:-\d+)?(?:-([0-9a-zA-Z]+))?$`)
	matches := re.FindStringSubmatch(input)

	if len(matches) > 0 {
		version = matches[1] // Capture the version number
		if len(matches) >= 3 && matches[2] != "" {
			revision = matches[2] // Update the revision if present
		}
		// If no new revision part is found, the original revision remains unchanged
	} else {
		// Handle the case where the input does not match the expected format
		version = input // Default to the input as is
	}

	return version, revision
}

type Imp struct {
	info      version.Info
	GoVersion string
	GoOS      string
	GoArch    string
}

func (i *Imp) prepareVersion() {
	i.info.Version, i.info.Revision = parseVersion(i.info.Version, i.info.Revision)
}

// Print returns version information.
func (i *Imp) Print() string {
	i.prepareVersion()
	m := map[string]string{
		"program":   i.info.Program,
		"version":   i.info.Version,
		"revision":  i.info.Revision,
		"branch":    i.info.Branch,
		"buildUser": i.info.BuildUser,
		"buildDate": i.info.BuildDate,
		"goVersion": i.GoVersion,
		"goOS":      i.GoOS,
		"goArch":    i.GoArch,
	}
	t := template.Must(template.New("version").Parse(versionInfoTmpl))

	var buf bytes.Buffer
	if err := t.ExecuteTemplate(&buf, "version", m); err != nil {
		panic(err)
	}
	return strings.TrimSpace(buf.String())
}

func (i *Imp) Short() string {
	if len(i.info.Revision) == 0 {
		return i.info.Version
	}
	return fmt.Sprintf("%s-%s", i.info.Version, i.info.Revision)
}

func (i *Imp) Info() string {
	i.prepareVersion()
	return fmt.Sprintf("(version=%s, branch=%s, revision=%s)", i.info.Version, i.info.Branch, i.info.Revision)
}

func (i *Imp) Context() string {
	return fmt.Sprintf("(go=%s, OS=%s, arch=%s user=%s, date=%s)", i.GoVersion, i.GoOS, i.GoArch, i.info.BuildUser, i.info.BuildDate)
}

func (i *Imp) Program() string {
	return i.info.Program
}

func Create(info *version.Info) *Imp {
	return &Imp{
		info:      *info,
		GoVersion: runtime.Version(),
		GoOS:      runtime.GOOS,
		GoArch:    runtime.GOARCH,
	}
}
