package flag

import (
	"strings"

	"golang.org/x/exp/slices"

	"github.com/aquasecurity/trivy/pkg/log"
	"github.com/aquasecurity/trivy/pkg/types"
)

var (
	VulnTypeFlag = Flag{
		Name:       "vuln-type",
		ConfigName: "vulnerability.type",
		Value:      strings.Join([]string{types.VulnTypeOS, types.VulnTypeLibrary}, ","),
		Usage:      "comma-separated list of vulnerability types (os,library)",
	}
	IgnoreUnfixedFlag = Flag{
		Name:       "ignore-unfixed",
		ConfigName: "vulnerability.ignore-unfixed",
		Value:      false,
		Usage:      "display only fixed vulnerabilities",
	}
)

type VulnerabilityFlagGroup struct {
	VulnType      *Flag
	IgnoreUnfixed *Flag
}

type VulnerabilityOptions struct {
	VulnType      []string
	IgnoreUnfixed bool
}

func NewVulnerabilityFlagGroup() *VulnerabilityFlagGroup {
	return &VulnerabilityFlagGroup{
		VulnType:      &VulnTypeFlag,
		IgnoreUnfixed: &IgnoreUnfixedFlag,
	}
}

func (f *VulnerabilityFlagGroup) Name() string {
	return "Vulnerability"
}

func (f *VulnerabilityFlagGroup) Flags() []*Flag {
	return []*Flag{f.VulnType, f.IgnoreUnfixed}
}

func (f *VulnerabilityFlagGroup) ToOptions() VulnerabilityOptions {
	return VulnerabilityOptions{
		VulnType:      parseVulnType(getStringSlice(f.VulnType)),
		IgnoreUnfixed: getBool(f.IgnoreUnfixed),
	}
}

func parseVulnType(vulnType []string) []string {
	switch {
	case len(vulnType) == 0: // no types
		return nil
	case len(vulnType) == 1 && strings.Contains(vulnType[0], ","): // get checks from flag
		vulnType = strings.Split(vulnType[0], ",")
	}

	var vulnTypes []string
	for _, v := range vulnType {
		if !slices.Contains(types.VulnTypes, v) {
			log.Logger.Warnf("unknown vulnerability type: %s", v)
			continue
		}
		vulnTypes = append(vulnTypes, v)
	}
	return vulnTypes
}
