package regionalapi

import (
	"encoding/json"
	"fmt"
	"net/url"

	clusterv1 "github.com/tidbcloud/infra-provider/api/tidbcloud/cluster-server/v1"
	"google.golang.org/protobuf/encoding/protojson"
	"google.golang.org/protobuf/proto"
	corev1 "k8s.io/api/core/v1"
)

// convertEnvVarsToMap converts []corev1.EnvVar to map[string]string
// This is used for regional API calls where env vars are represented as a map
func convertEnvVarsToMap(envVars []corev1.EnvVar) map[string]string {
	result := make(map[string]string, len(envVars))
	if len(envVars) == 0 {
		return result
	}
	for _, env := range envVars {
		// Only convert simple key-value pairs, ignore ValueFrom
		if env.ValueFrom == nil {
			result[env.Name] = env.Value
		}
	}
	return result
}

// convertResourceRequirements converts *corev1.ResourceRequirements to *clusterv1.ResourceRequirements
// This is used for regional API calls where resource requirements use map[string]string
func convertResourceRequirements(req *corev1.ResourceRequirements) *clusterv1.ResourceRequirements {
	if req == nil {
		return nil
	}
	result := &clusterv1.ResourceRequirements{
		Requests: map[string]string{},
		Limits:   map[string]string{},
	}
	for k, v := range req.Limits {
		result.Limits[string(k)] = v.String()
	}
	for k, v := range req.Requests {
		result.Requests[string(k)] = v.String()
	}
	return result
}

func proto2QueryParams(obj proto.Message) (url.Values, error) {
	m, err := proto2Map(obj)
	if err != nil {
		return nil, err
	}

	params := make(url.Values, len(m))
	for k, v := range m {
		switch val := v.(type) {
		case string:
			params.Set(k, val)
		case []string:
			for _, s := range val {
				params.Add(k, s)
			}
		case []any:
			for _, a := range val {
				params.Add(k, fmt.Sprintf("%v", a))
			}
		default:
			params.Set(k, fmt.Sprintf("%v", val))
		}
	}
	return params, nil
}

func proto2Map(obj proto.Message) (map[string]any, error) {
	b, err := protojson.Marshal(obj)
	if err != nil {
		return nil, err
	}
	m := make(map[string]any)
	err = json.Unmarshal(b, &m)
	if err != nil {
		return nil, err
	}
	return m, nil
}
