package rosa

import (
	"path"
	"slices"
	"strconv"
	"strings"

	"hakurei.app/internal/pkg"
)

const (
	// jobsE is expression for preferred job count set by [pkg].
	jobsE = `"$` + pkg.EnvJobs + `"`
	// jobsFlagE is expression for flag with preferred job count.
	jobsFlagE = `"-j$` + pkg.EnvJobs + `"`
	// jobsLE is expression for twice of preferred job count set by [pkg].
	jobsLE = `"$(expr ` + jobsE + ` '*' 2)"`
	// jobsLFlagE is expression for flag with double of preferred job count.
	jobsLFlagE = `"-j$(expr ` + jobsE + ` '*' 2)"`

	// loadE is expression for preferred loadavg target set by [pkg].
	loadE = `"$` + pkg.EnvLoad + `"`
	// loadFlagE is expression for flag with preferred loadavg target.
	loadFlagE = `"-l$` + pkg.EnvLoad + `"`
)

// newTar wraps [pkg.NewHTTPGetTar] with a simpler function signature.
func newTar(url, checksum string, compress uint32) pkg.Artifact {
	return pkg.NewTar(
		pkg.NewDecompress(
			pkg.NewHTTPGet(nil, url, mustDecode(checksum)),
			compress,
		),
	)
}

// newFromCPAN is a helper for downloading release from CPAN.
func newFromCPAN(author, name, version, checksum string) pkg.Artifact {
	return newTar(
		"https://cpan.metacpan.org/authors/id/"+
			author[:1]+"/"+author[:2]+"/"+author+"/"+
			name+"-"+version+".tar.gz",
		checksum,
		pkg.Gzip,
	)
}

// newFromGitLab is a helper for downloading source from GitLab.
func newFromGitLab(domain, suffix, ref, checksum string) pkg.Artifact {
	return newTar(
		"https://"+domain+"/"+suffix+"/-/archive/"+
			ref+"/"+path.Base(suffix)+"-"+
			strings.ReplaceAll(ref, "/", "-")+".tar.bz2",
		checksum,
		pkg.Bzip2,
	)
}

// newFromGitHub is a helper for downloading source from Microsoft Github.
func newFromGitHub(suffix, tag, checksum string) pkg.Artifact {
	return newTar(
		"https://github.com/"+suffix+
			"/archive/refs/tags/"+tag+".tar.gz",
		checksum,
		pkg.Gzip,
	)
}

// newFromGitHubRelease is a helper for downloading release tarball from
// Microsoft Github.
func newFromGitHubRelease(
	suffix, tag, name, checksum string,
	compression uint32,
) pkg.Artifact {
	return newTar(
		"https://github.com/"+suffix+
			"/releases/download/"+tag+"/"+name,
		checksum,
		compression,
	)
}

// skipGNUTests generates a string for skipping specific tests by number in a
// GNU test suite. This is nontrivial because the test suite does not support
// excluding tests in any way, so ranges for all but the skipped tests have to
// be specified instead.
//
// For example, to skip test 764, ranges around the skipped test must be
// specified:
//
//	1-763 765-
//
// Tests are numbered starting from 1. The resulting string is unquoted.
func skipGNUTests(tests ...int64) string {
	tests = slices.Clone(tests)
	slices.Sort(tests)

	var buf strings.Builder

	if tests[0] != 1 {
		buf.WriteString("1-")
	}

	for i, n := range tests {
		if n != 1 && (i == 0 || tests[i-1] != n-1) {
			buf.WriteString(strconv.Itoa(int(n - 1)))
			buf.WriteString(" ")
		}
		if i == len(tests)-1 || (tests[i+1] != n+1 && tests[i+1] != n+2) {
			buf.WriteString(strconv.Itoa(int(n + 1)))
			buf.WriteString("-")
		}
	}
	return buf.String()
}
