package pipeline

import (
	"fmt"

	"sigs.k8s.io/yaml"
)

func PatchDedicatedClusterCPUConfigYAML(configYAML string, components []ClusterComponent) (string, error) {
	components = filterSupportedPipelineComponents(components)
	if len(components) == 0 {
		return configYAML, nil
	}

	var cfg map[string]interface{}
	if err := yaml.Unmarshal([]byte(configYAML), &cfg); err != nil {
		return "", fmt.Errorf("failed to unmarshal pipeline runtime config yaml: %w", err)
	}

	rawTargetClusters, ok := cfg["targetClusters"].([]interface{})
	if !ok || len(rawTargetClusters) == 0 {
		return "", fmt.Errorf("pipeline runtime config missing targetClusters")
	}

	clusterConfig, ok := rawTargetClusters[0].(map[string]interface{})
	if !ok {
		return "", fmt.Errorf("pipeline runtime config targetClusters[0] is invalid")
	}

	rawComponents, ok := clusterConfig["components"].([]interface{})
	if !ok {
		return "", fmt.Errorf("pipeline runtime config targetClusters[0].components is invalid")
	}

	cpuByComponentType := make(map[string]int64, len(components))
	existingComponentTypes := make(map[string]struct{}, len(rawComponents))
	for _, comp := range components {
		cpuByComponentType[comp.ComponentType] = comp.CpuNum
	}

	filteredRawComponents := make([]interface{}, 0, len(rawComponents))
	for _, rawComponent := range rawComponents {
		componentMap, ok := rawComponent.(map[string]interface{})
		if !ok {
			continue
		}
		componentType, ok := componentMap["componentType"].(string)
		if !ok {
			continue
		}
		if !IsSupportedPipelineComponentType(componentType) {
			// Intentionally drop unsupported component entries already present in runtime
			// config. Keeping them here can crash pipeline on reload; do not turn this back
			// into a hard failure unless pipeline learns how to process those components.
			continue
		}
		existingComponentTypes[componentType] = struct{}{}
		if cpuNum, ok := cpuByComponentType[componentType]; ok {
			componentMap["cpuNum"] = cpuNum
		}
		filteredRawComponents = append(filteredRawComponents, componentMap)
	}
	rawComponents = filteredRawComponents

	for _, component := range components {
		if _, exists := existingComponentTypes[component.ComponentType]; exists {
			continue
		}
		rawComponents = append(rawComponents, map[string]interface{}{
			"componentType": component.ComponentType,
			"cpuNum":        component.CpuNum,
		})
	}
	clusterConfig["components"] = rawComponents

	result, err := yaml.Marshal(cfg)
	if err != nil {
		return "", fmt.Errorf("failed to marshal patched pipeline runtime config yaml: %w", err)
	}
	return string(result), nil
}
