package logger

import (
	"bytes"
	"encoding/json"
	"log/slog"
	"strings"
	"testing"

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

func TestAuditLogEntry_RedactsSensitiveFields(t *testing.T) {
	buf := &bytes.Buffer{}
	previous := slog.Default()
	slog.SetDefault(slog.New(slog.NewJSONHandler(buf, nil)))
	defer slog.SetDefault(previous)

	ale := &AuditLogEntry{
		RequestID:        "req-1",
		Stage:            "login",
		Token:            "tok-secret",
		RefreshToken:     "refresh-secret",
		SessionJwt:       "session-secret",
		AccessJwt:        "access-secret",
		SetCookieName:    "sid",
		SetCookieValue:   "cookie-secret",
		ParsedCookieDSRF: "dsrf-secret",
		LoginIDs: map[string]string{
			"loginId": "user@example.com",
		},
		Query: map[string]string{
			"token":  "query-token",
			"locale": "ko",
		},
		Headers: map[string]string{
			"Authorization": "Bearer secret",
			"Cookie":        "session=secret",
		},
	}

	ale.Log(slog.LevelInfo, "test")

	line := strings.TrimSpace(buf.String())
	require.NotEmpty(t, line)

	var payload map[string]any
	require.NoError(t, json.Unmarshal([]byte(line), &payload))

	assert.NotContains(t, payload, "token")
	assert.NotContains(t, payload, "refresh_token")
	assert.NotContains(t, payload, "session_jwt")
	assert.NotContains(t, payload, "access_jwt")
	assert.NotContains(t, payload, "set_cookie_value")
	assert.NotContains(t, payload, "parsed_cookie_DSRF")
	assert.NotContains(t, payload, "request_body")
	assert.NotContains(t, payload, "new_password")

	assert.Equal(t, true, payload["has_token"])
	assert.Equal(t, true, payload["has_refresh_token"])
	assert.Equal(t, true, payload["has_session_jwt"])
	assert.Equal(t, true, payload["has_access_jwt"])
	assert.Equal(t, true, payload["has_set_cookie_value"])
	assert.Equal(t, true, payload["has_parsed_cookie_DSRF"])

	loginIDs, ok := payload["login_ids"].(map[string]any)
	require.True(t, ok)
	assert.Equal(t, "user@example.com", loginIDs["loginId"])

	query, ok := payload["query"].(map[string]any)
	require.True(t, ok)
	assert.Equal(t, "*****", query["token"])
	assert.Equal(t, "ko", query["locale"])

	headers, ok := payload["headers"].(map[string]any)
	require.True(t, ok)
	assert.Equal(t, "*****", headers["Authorization"])
	assert.Equal(t, "*****", headers["Cookie"])
}
