package version

import (
	"testing"

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

var (
	fakeGitLabReleasesList = []string{
		"18.0",
		"17.11", "17.10", "17.9", "17.8", "17.7", "17.6", "17.5", "17.4", "17.3", "17.2", "17.1", "17.0",
		"16.11", "16.10", "16.9", "16.8", "16.7", "16.6", "16.5", "16.4", "16.3", "16.2", "16.1", "16.0",
	}
)

func TestSemver_AgentOutdatedWarning(t *testing.T) {
	tests := []struct {
		name          string
		serverVersion Version
		agentVersion  Version
		typ           AgentVersionWarningType
		warning       string
	}{
		{
			name:          "exact same server and agent version",
			serverVersion: mustParseVersion(t, "v17.1.0"),
			agentVersion:  mustParseVersion(t, "v17.1.0"),
			typ:           AgentVersionNoWarning,
		},
		{
			name:          "agent older than server, patch doesn't matter",
			serverVersion: mustParseVersion(t, "v17.1.9"),
			agentVersion:  mustParseVersion(t, "v17.1.0"),
			typ:           AgentVersionNoWarning,
		},
		{
			name:          "agent older than server, but in ok range",
			serverVersion: mustParseVersion(t, "v17.5.0"),
			agentVersion:  mustParseVersion(t, "v17.1.0"),
			typ:           AgentVersionNoWarning,
		},
		{
			name:          "agent older than server, is outdated",
			serverVersion: mustParseVersion(t, "v17.5.0"),
			agentVersion:  mustParseVersion(t, "v17.0.0"),
			typ:           AgentVersionOutdated,
			warning:       "The agent for Kubernetes (agentk) is outdated by more than four minor releases and might not be compatible with the agent server for Kubernetes (KAS). You should upgrade agentk.",
		},
		{
			name:          "agent older than server in pre-release, okay",
			serverVersion: mustParseVersion(t, "v17.5.0-rc1"),
			agentVersion:  mustParseVersion(t, "v17.0.0"),
			typ:           AgentVersionNoWarning,
		},
		{
			name:          "agent older than server, major doesn't match but in range",
			serverVersion: mustParseVersion(t, "v17.2.0"),
			agentVersion:  mustParseVersion(t, "v16.10.0"),
			typ:           AgentVersionNoWarning,
			warning:       "",
		},
		{
			name:          "agent older than server, major doesn't match and outdated",
			serverVersion: mustParseVersion(t, "v17.2.0"),
			agentVersion:  mustParseVersion(t, "v16.9.0"),
			typ:           AgentVersionOutdated,
			warning:       "The agent for Kubernetes (agentk) is outdated by more than four minor releases, including a major release, and might not be compatible with the agent server for Kubernetes (KAS). You should upgrade agentk.",
		},
		{
			name:          "agent newer than server, patch doesn't matter",
			serverVersion: mustParseVersion(t, "v17.1.0"),
			agentVersion:  mustParseVersion(t, "v17.1.9"),
			typ:           AgentVersionNoWarning,
		},
		{
			name:          "agent newer than server, but in ok range",
			serverVersion: mustParseVersion(t, "v17.1.0"),
			agentVersion:  mustParseVersion(t, "v17.5.0"),
			typ:           AgentVersionNoWarning,
		},
		{
			name:          "agent newer than server, is too new",
			serverVersion: mustParseVersion(t, "v17.0.0"),
			agentVersion:  mustParseVersion(t, "v17.5.0"),
			typ:           AgentVersionTooNew,
			warning:       "The agent for Kubernetes (agentk) is more than four minor releases ahead of the agent server for Kubernetes (KAS). You should downgrade agentk to match KAS.",
		},
		{
			name:          "agent newer than server, major doesn't match but in range",
			serverVersion: mustParseVersion(t, "v16.10.0"),
			agentVersion:  mustParseVersion(t, "v17.2.0"),
			typ:           AgentVersionNoWarning,
			warning:       "",
		},
		{
			name:          "agent newer than server, major doesn't match and too new",
			serverVersion: mustParseVersion(t, "v16.9.0"),
			agentVersion:  mustParseVersion(t, "v17.2.0"),
			typ:           AgentVersionTooNew,
			warning:       "The agent for Kubernetes (agentk) is more than four minor releases ahead of the agent server for Kubernetes (KAS), including a major release. You should downgrade agentk to match KAS.",
		},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			typ, warning := WarningIfOutdatedAgent(tc.serverVersion, tc.agentVersion, fakeGitLabReleasesList)

			assert.Equal(t, tc.typ, typ)
			assert.Equal(t, tc.warning, warning)
		})
	}
}

func mustParseVersion(t *testing.T, v string) Version {
	t.Helper()

	version, err := NewVersion(v)
	require.NoError(t, err)
	return version
}
