package maximizer

// ScoreWeights controls the balance between safety and business utility.
type ScoreWeights struct {
	Safety  float64 `json:"safety"`
	Utility float64 `json:"utility"`
}

// DefaultWeights prioritizes business utility slightly over safety margin
// since the optimizer already ensures compliance.
var DefaultWeights = ScoreWeights{Safety: 0.4, Utility: 0.6}

// dimensionBusinessWeight indicates how much business value each dimension
// contributes. Higher = more costly to change for the business.
var dimensionBusinessWeight = map[string]int{
	"automation_level":      15,
	"decision_binding":      12,
	"deployment_scope":      10,
	"model_type":            8,
	"decision_impact":       7,
	"explainability":        5,
	"data_type":             5,
	"human_in_loop":         5,
	"legal_basis":           4,
	"domain":                3,
	"risk_classification":   3,
	"transparency_required": 2,
	"logging_required":      2,
}

// ComputeSafetyScore returns 0-100 where 100 = completely safe (no restrictions).
// Decreases with each RESTRICTED or FORBIDDEN zone.
func ComputeSafetyScore(eval *EvaluationResult) int {
	if eval == nil {
		return 0
	}
	total := len(allDimensions)
	safe := 0
	for _, zi := range eval.ZoneMap {
		if zi.Zone == ZoneSafe {
			safe++
		}
	}
	if total == 0 {
		return 100
	}
	return (safe * 100) / total
}

// ComputeUtilityScore returns 0-100 where 100 = no changes from original.
// Decreases based on the business weight of each changed dimension.
func ComputeUtilityScore(original, variant *DimensionConfig) int {
	if original == nil || variant == nil {
		return 0
	}
	deltas := original.Diff(variant)
	if len(deltas) == 0 {
		return 100
	}

	maxCost := 0
	for _, w := range dimensionBusinessWeight {
		maxCost += w
	}

	cost := 0
	for _, d := range deltas {
		w := dimensionBusinessWeight[d.Dimension]
		if w == 0 {
			w = 3 // default
		}
		cost += w
	}

	if cost >= maxCost {
		return 0
	}
	return 100 - (cost*100)/maxCost
}

// ComputeCompositeScore combines safety and utility into a single ranking score.
func ComputeCompositeScore(safety, utility int, weights ScoreWeights) float64 {
	return weights.Safety*float64(safety) + weights.Utility*float64(utility)
}
