// Copyright 2020-2026 Project Capsule Authors
// SPDX-License-Identifier: Apache-2.0

package quota

import (
	"fmt"
	"strconv"
	"strings"

	"k8s.io/apimachinery/pkg/api/resource"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

	"github.com/projectcapsule/capsule/pkg/runtime/jsonpath"
)

func ParseBoolFromUnstructured(u unstructured.Unstructured, compiled *jsonpath.CompiledJSONPath) (bool, error) {
	value, err := ParseUsageFromUnstructured(u, compiled)
	if err != nil {
		return false, err
	}

	value = strings.TrimSpace(value)
	if value == "" {
		return false, nil
	}

	parsed, err := strconv.ParseBool(value)
	if err != nil {
		return false, fmt.Errorf("condition path %v did not resolve to a boolean, got %q: %w", compiled, value, err)
	}

	return parsed, nil
}

func ConditionsMatch(u unstructured.Unstructured, conditions []*jsonpath.CompiledJSONPath) (bool, error) {
	for _, cond := range conditions {
		ok, err := ParseBoolFromUnstructured(u, cond)
		if err != nil {
			return false, err
		}

		if !ok {
			return false, nil
		}
	}

	return true, nil
}

func ParseQuantities(value string) (resource.Quantity, error) {
	fields := strings.Fields(value)
	if len(fields) == 0 {
		return resource.Quantity{}, fmt.Errorf("no quantity values found")
	}

	total := resource.Quantity{}

	for _, v := range fields {
		q, err := resource.ParseQuantity(v)
		if err != nil {
			return total, fmt.Errorf("invalid quantity %q: %w", v, err)
		}

		total.Add(q)
	}

	return total, nil
}

// GetUsageFromUnstructured extracts a value from an unstructured object using a JSONPath source path.
// It is convenient for one-off calls. For repeated calls with the same sourcePath, prefer
// CompileUsageJSONPath(...) and then Execute(...) to avoid reparsing.
func ParseUsageFromUnstructured(u unstructured.Unstructured, compiled *jsonpath.CompiledJSONPath) (string, error) {
	return compiled.Execute(u)
}

func ParseQuantityFromUnstructured(u unstructured.Unstructured, compiled *jsonpath.CompiledJSONPath) (resource.Quantity, error) {
	usage, err := ParseUsageFromUnstructured(u, compiled)
	if err != nil {
		return resource.Quantity{}, err
	}

	if strings.TrimSpace(usage) == "" {
		return resource.Quantity{}, fmt.Errorf("quantity path did not resolve to any value")
	}

	return ParseQuantities(usage)
}
