package signature

import (
	"crypto/sha256"
	"fmt"
	"net/url"
	"sort"
	"strings"
)

// BuildStringToSign StringToSign = METHOD\nPATH\nCANONICAL_QUERY\nBODY_SHA256\nX-App-Id\nX-Timestamp\nX-Nonce
func BuildStringToSign(method, path, rawQuery string, body []byte, appId, timestamp, nonce string) string {
	canonical := canonicalQuery(rawQuery)
	bodyHash := sha256Hex(body)
	parts := []string{
		strings.ToUpper(method),
		path,
		canonical,
		bodyHash,
		appId,
		timestamp,
		nonce,
	}
	return strings.Join(parts, "\n")
}

func canonicalQuery(rawQuery string) string {
	if rawQuery == "" {
		return ""
	}
	values, err := url.ParseQuery(rawQuery)
	if err != nil {
		return rawQuery
	}
	keys := make([]string, 0, len(values))
	for key := range values {
		keys = append(keys, key)
	}
	sort.Strings(keys)
	parts := make([]string, 0, len(keys))
	for _, key := range keys {
		parts = append(parts, fmt.Sprintf("%s=%s", key, values.Get(key)))
	}
	return strings.Join(parts, "&")
}

func sha256Hex(data []byte) string {
	h := sha256.Sum256(data)
	return fmt.Sprintf("%x", h)
}
