package server

import (
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/tool/testing/matcher"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/pkg/agentcfg"
	"google.golang.org/protobuf/encoding/protojson"
)

func TestApplyDefaultsToAgentConfig(t *testing.T) {
	cfg := &agentcfg.ConfigurationFile{
		CiAccess: &agentcfg.CiAccessCF{
			Projects: []*agentcfg.CiAccessProjectCF{
				{},
			},
			Groups: []*agentcfg.CiAccessGroupCF{
				{},
			},
		},
		UserAccess: &agentcfg.UserAccessCF{},
	}
	cfgExpected := &agentcfg.ConfigurationFile{
		CiAccess: &agentcfg.CiAccessCF{
			Projects: []*agentcfg.CiAccessProjectCF{
				{
					AccessAs: &agentcfg.CiAccessAsCF{
						As: &agentcfg.CiAccessAsCF_Agent{
							Agent: &agentcfg.CiAccessAsAgentCF{},
						},
					},
				},
			},
			Groups: []*agentcfg.CiAccessGroupCF{
				{
					AccessAs: &agentcfg.CiAccessAsCF{
						As: &agentcfg.CiAccessAsCF_Agent{
							Agent: &agentcfg.CiAccessAsAgentCF{},
						},
					},
				},
			},
		},
		UserAccess: &agentcfg.UserAccessCF{
			AccessAs: &agentcfg.UserAccessAsCF{
				As: &agentcfg.UserAccessAsCF_Agent{
					Agent: &agentcfg.UserAccessAsAgentCF{},
				},
			},
		},
	}

	ApplyDefaultsToAgentConfig(cfg)

	matcher.AssertProtoEqual(t, cfgExpected, cfg)

	data, err := protojson.Marshal(cfg)
	require.NoError(t, err)

	// protojson.Marshal() produces unstable output. Unmarshal into a map to compare for equality.
	// See https://github.com/golang/protobuf/issues/1121
	var rawData any
	err = json.Unmarshal(data, &rawData)
	require.NoError(t, err)

	expectedRawData := map[string]any{
		"ci_access": map[string]any{
			"projects": []any{
				map[string]any{
					"access_as": map[string]any{
						"agent": map[string]any{}},
				},
			},
			"groups": []any{
				map[string]any{
					"access_as": map[string]any{
						"agent": map[string]any{}},
				},
			},
		},
		"user_access": map[string]any{
			"access_as": map[string]any{
				"agent": map[string]any{},
			},
		},
	}

	assert.Equal(t, expectedRawData, rawData)
}
