package redact

import (
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

type bad struct {
	Ban     string
	ABanC   string
	private string
	Public  string
}

func TestAsMapRedactKeys(t *testing.T) {
	banned := []string{"ban"}
	out, err := AsMapRedactKeys(banned, nil)
	assert.Nil(t, err)
	assert.Nil(t, out)
	b := bad{Ban: "secret", ABanC: "ABanC", Public: "okay", private: "private"}
	result := map[string]interface{}{"Ban": "redacted", "ABanC": "redacted", "Public": "okay"}
	out, err = AsMapRedactKeys(banned, b)
	assert.Nil(t, err)
	assert.Equal(t, result, out)
	out, err = AsMapRedactKeys(banned, &b)
	assert.Nil(t, err)
	assert.Equal(t, result, out)
}

func TestRedactKeysToJSONPreservesLargeUint64(t *testing.T) {
	type request struct {
		TiDBClusterID uint64 `json:"tidb_cluster_id"`
	}

	payload, err := RedactKeysToJSON(nil, request{TiDBClusterID: 2067140380859564032})
	require.NoError(t, err)
	assert.JSONEq(t, `{"tidb_cluster_id":2067140380859564032}`, string(payload))

	var decoded map[string]json.Number
	require.NoError(t, json.Unmarshal(payload, &decoded))
	assert.Equal(t, json.Number("2067140380859564032"), decoded["tidb_cluster_id"])
}

func TestRedactKeysToJSONPreservesPrimitiveSlices(t *testing.T) {
	type credential struct {
		Name     string `json:"name"`
		Password string `json:"password"`
	}
	type request struct {
		EndpointZones []string     `json:"endpoint_zones"`
		Credentials   []credential `json:"credentials"`
	}

	payload, err := RedactKeysToJSON(PasswordFields, request{
		EndpointZones: []string{"cn-hongkong-c", "cn-hongkong-d"},
		Credentials: []credential{
			{Name: "mysql", Password: "secret"},
		},
	})
	require.NoError(t, err)
	assert.JSONEq(t, `{
		"endpoint_zones":["cn-hongkong-c","cn-hongkong-d"],
		"credentials":[{"name":"mysql","password":"redacted"}]
	}`, string(payload))
}
