package qobuz

import (
	"crypto/md5"
	"encoding/hex"
	"net/url"
	"sort"
	"strings"
	"time"
)

func signGet(path, appSecret string, query url.Values) (requestTS, requestSig string) {
	ts := nowTS()
	method := methodName(path)

	keys := make([]string, 0, len(query))
	for k := range query {
		if k == "app_id" || k == "request_ts" || k == "request_sig" {
			continue
		}
		keys = append(keys, k)
	}
	sort.Strings(keys)

	b := strings.Builder{}
	b.WriteString(method)
	for _, k := range keys {
		vals := query[k]
		if len(vals) == 0 {
			continue
		}
		b.WriteString(k)
		b.WriteString(vals[0])
	}
	b.WriteString(ts)
	b.WriteString(appSecret)

	h := md5.Sum([]byte(b.String()))
	return ts, hex.EncodeToString(h[:])
}

func signPost(path, appSecret string, form url.Values, includeValues bool) (requestTS, requestSig string) {
	ts := nowTS()
	method := methodName(path)

	keys := make([]string, 0, len(form))
	for k := range form {
		if k == "app_id" || k == "request_ts" || k == "request_sig" {
			continue
		}
		keys = append(keys, k)
	}
	sort.Strings(keys)

	b := strings.Builder{}
	b.WriteString(method)
	for _, k := range keys {
		b.WriteString(k)
		if includeValues {
			vals := form[k]
			if len(vals) > 0 {
				b.WriteString(vals[0])
			}
		}
	}
	b.WriteString(ts)
	b.WriteString(appSecret)

	h := md5.Sum([]byte(b.String()))
	return ts, hex.EncodeToString(h[:])
}

func methodName(path string) string {
	return strings.ReplaceAll(strings.Trim(path, "/"), "/", "")
}

func nowTS() string {
	return strconvI64(time.Now().Unix())
}

func strconvI64(v int64) string {
	if v == 0 {
		return "0"
	}
	neg := v < 0
	if neg {
		v = -v
	}
	buf := [20]byte{}
	i := len(buf)
	for v > 0 {
		i--
		buf[i] = byte('0' + v%10)
		v /= 10
	}
	if neg {
		i--
		buf[i] = '-'
	}
	return string(buf[i:])
}
