package api

import (
	"fmt"

	kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
	pssutils "github.com/kyverno/kyverno/pkg/pss/utils"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/pod-security-admission/api"
)

// PodSecurityChecks details about pod securty checks
type PodSecurityChecks struct {
	// Level is the pod security level
	Level api.Level
	// Version is the pod security version
	Version string
	// Checks contains check result details
	Checks []pssutils.PSSCheckResult
}

// RuleResponse details for each rule application
type RuleResponse struct {
	// Name is the rule name specified in policy
	Name string
	// Type is the rule type (Mutation,Generation,Validation) for Kyverno Policy
	Type RuleType
	// Message is the message response from the rule application
	Message string
	// Patches are JSON patches, for mutation rules
	Patches [][]byte
	// GeneratedResource is the generated by the generate rules of a policy
	GeneratedResource unstructured.Unstructured
	// Status rule status
	Status RuleStatus
	// Stats contains rule statistics
	Stats ExecutionStats
	// PatchedTarget is the patched resource for mutate.targets
	PatchedTarget *unstructured.Unstructured
	// PatchedTargetSubresourceName is the name of the subresource which is patched, empty if the resource patched is not a subresource.
	PatchedTargetSubresourceName string
	// PatchedTargetParentResourceGVR is the GVR of the parent resource of the PatchedTarget. This is only populated when PatchedTarget is a subresource.
	PatchedTargetParentResourceGVR metav1.GroupVersionResource
	// PodSecurityChecks contains pod security checks (only if this is a pod security rule)
	PodSecurityChecks *PodSecurityChecks
	// Exception is the exception applied (if any)
	Exception *kyvernov2alpha1.PolicyException
}

// HasStatus checks if rule status is in a given list
func (r RuleResponse) HasStatus(status ...RuleStatus) bool {
	for _, s := range status {
		if r.Status == s {
			return true
		}
	}
	return false
}

// String implements Stringer interface
func (r RuleResponse) String() string {
	return fmt.Sprintf("rule %s (%s): %v", r.Name, r.Type, r.Message)
}
