package config_center

import (
	"encoding/json"
	"sort"
	"strconv"

	"google.golang.org/protobuf/types/known/structpb"
)

func LinesMapToSlice(lines map[string]*ParamItem) []*ParamItem {
	var ids []string
	var result []*ParamItem
	for k := range lines {
		ids = append(ids, k)
	}

	sort.Slice(ids, func(i, j int) bool {
		in, _ := strconv.ParseUint(ids[i], 10, 64)
		jn, _ := strconv.ParseUint(ids[j], 10, 64)
		return in < jn
	})
	for _, id := range ids {
		result = append(result, lines[id])
	}
	return result
}

type DictValidation struct {
	Enum       []any    `json:"enum,omitempty"`
	MultipleOf *float64 `json:"multipleOf,omitempty"`
	Maximum    *float64 `json:"maximum,omitempty"`
	Minimum    *float64 `json:"minimum,omitempty"`
	Pattern    *string  `json:"pattern,omitempty"`
	// todo: validation for arrays and objects
}

func NewValue(v any) (*structpb.Value, error) {
	switch v := v.(type) {
	// As a workaround to handle []map[string]any parameter.
	// Only use in this case until full test coverage for existing data.
	case []map[string]any:
		return newAnyValue(v)
	default:
		return structpb.NewValue(v)
	}
}

// As https://github.com/golang/protobuf/issues/1302#issuecomment-805453221 described,
// we can't use structpb.NewValue with any type. Json marshal and unmarshal is expected in this case.
func newAnyValue(v any) (*structpb.Value, error) {
	buf, err := json.Marshal(v)
	if err != nil {
		return nil, err
	}
	var value structpb.Value
	err = value.UnmarshalJSON(buf)
	return &value, err
}
