package packages

import (
	"bufio"
	"errors"
	"io"
	"os"
	"runtime"
	"strings"
)

// OSRelease identifies the distribution well enough to select an advisory
// feed. VersionID is not optional: Ubuntu 22.04 and 24.04 publish different
// fixed versions for the same CVE.
type OSRelease struct {
	Family    string
	VersionID string
	Arch      string
}

// ParseOSRelease reads the os-release format: KEY=value, one per line, with
// values optionally quoted, and # comments.
//
// The quote stripping handles both ID=ubuntu and ID="rocky", which real
// distributions both emit.
func ParseOSRelease(r io.Reader) (OSRelease, error) {
	out := OSRelease{Arch: runtime.GOARCH}
	sc := bufio.NewScanner(r)
	for sc.Scan() {
		line := strings.TrimSpace(sc.Text())
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}
		key, val, ok := strings.Cut(line, "=")
		if !ok {
			continue
		}
		val = strings.Trim(strings.TrimSpace(val), `"'`)
		switch strings.TrimSpace(key) {
		case "ID":
			out.Family = strings.ToLower(val)
		case "VERSION_ID":
			out.VersionID = val
		}
	}
	if err := sc.Err(); err != nil {
		return OSRelease{}, err
	}
	if out.Family == "" {
		return OSRelease{}, errors.New("os-release has no ID")
	}
	return out, nil
}

// DetectOS reads /etc/os-release.
func DetectOS() (OSRelease, error) {
	f, err := os.Open("/etc/os-release")
	if err != nil {
		return OSRelease{}, err
	}
	defer f.Close()
	return ParseOSRelease(f)
}
