//
// Copyright 2021, Paul Shoemaker
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package gitlab

import (
	"fmt"
	"net/http"
	"testing"

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

func TestGroupListClusters(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	mux.HandleFunc("/api/v4/groups/26/clusters", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		fmt.Fprintf(w, `[
			{
			  "id":18,
			  "name":"cluster-1",
			  "domain":"example.com",
			  "created_at":"2019-01-02T20:18:12.563Z",
			  "managed": true,
			  "enabled": true,
			  "provider_type":"user",
			  "platform_type":"kubernetes",
			  "environment_scope":"*",
			  "cluster_type":"group_type",
			  "user": {
				"id":1,
				"name":"Administrator",
				"username":"root",
				"state":"active",
				"avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..",
				"web_url":"https://gitlab.example.com/root"
			  },
			  "platform_kubernetes": {
				"api_url":"https://104.197.68.152",
				"authorization_type":"rbac",
				"ca_cert":"-----BEGIN CERTIFICATE-----\r\nAAAAA\r\n-----END CERTIFICATE-----"
			  },
			  "management_project": {
				"id":2,
				"description":"sdhfgnbsdjfhg",
				"name":"project2",
				"name_with_namespace":"John Doe8 / project2",
				"path":"project2",
				"path_with_namespace":"namespace2/project2",
				"created_at":"2019-10-11T02:55:54.138Z"
			  }
			},
			{
			  "id":19,
			  "name":"cluster-2"
			}
		]`)
	})

	clusters, _, err := client.GroupCluster.ListClusters(26)
	require.NoError(t, err)

	want := []*GroupCluster{
		{
			ID:               18,
			Name:             "cluster-1",
			Domain:           "example.com",
			CreatedAt:        mustParseTime("2019-01-02T20:18:12.563Z"),
			Managed:          true,
			Enabled:          true,
			ProviderType:     "user",
			PlatformType:     "kubernetes",
			EnvironmentScope: "*",
			ClusterType:      "group_type",
			User: &User{
				ID:        1,
				Name:      "Administrator",
				Username:  "root",
				State:     "active",
				AvatarURL: "https://www.gravatar.com/avatar/4249f4df72b..",
				WebURL:    "https://gitlab.example.com/root",
			},
			PlatformKubernetes: &PlatformKubernetes{
				APIURL:            "https://104.197.68.152",
				AuthorizationType: "rbac",
				CaCert:            "-----BEGIN CERTIFICATE-----\r\nAAAAA\r\n-----END CERTIFICATE-----",
			},
			ManagementProject: &ManagementProject{
				ID:                2,
				Description:       "sdhfgnbsdjfhg",
				Name:              "project2",
				NameWithNamespace: "John Doe8 / project2",
				Path:              "project2",
				PathWithNamespace: "namespace2/project2",
				CreatedAt:         mustParseTime("2019-10-11T02:55:54.138Z"),
			},
		},
		{
			ID:   19,
			Name: "cluster-2",
		},
	}

	assert.Equal(t, want, clusters)
}

func TestGetGroupCluster(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	mux.HandleFunc("/api/v4/groups/26/clusters/18", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		fmt.Fprintf(w, `{
			"id":18,
			"name":"cluster-1",
			"domain":"example.com",
			"created_at":"2019-01-02T20:18:12.563Z",
			"managed": true,
			"enabled": true,
			"provider_type":"user",
			"platform_type":"kubernetes",
			"environment_scope":"*",
			"cluster_type":"group_type",
			"user": {
			  "id":1,
			  "name":"Administrator",
			  "username":"root",
			  "state":"active",
			  "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..",
			  "web_url":"https://gitlab.example.com/root"
			},
			"platform_kubernetes": {
			  "api_url":"https://104.197.68.152",
			  "authorization_type":"rbac",
			  "ca_cert":"-----BEGIN CERTIFICATE-----\r\nAAAAA\r\n-----END CERTIFICATE-----"
			},
			"management_project": {
			  "id":2,
			  "description":"skjdfgsdfg",
			  "name":"project2",
			  "name_with_namespace":"John Doe8 / project2",
			  "path":"project2",
			  "path_with_namespace":"namespace2/project2",
			  "created_at":"2019-10-11T02:55:54.138Z"
			},
			"group": {
			  "id":26,
			  "name":"group-with-clusters-api",
			  "web_url":"https://gitlab.example.com/group-with-clusters-api"
			}
		}`)
	})

	cluster, _, err := client.GroupCluster.GetCluster(26, 18)
	require.NoError(t, err)

	want := &GroupCluster{
		ID:               18,
		Name:             "cluster-1",
		Domain:           "example.com",
		CreatedAt:        mustParseTime("2019-01-02T20:18:12.563Z"),
		Managed:          true,
		Enabled:          true,
		ProviderType:     "user",
		PlatformType:     "kubernetes",
		EnvironmentScope: "*",
		ClusterType:      "group_type",
		User: &User{
			ID:        1,
			Name:      "Administrator",
			Username:  "root",
			State:     "active",
			AvatarURL: "https://www.gravatar.com/avatar/4249f4df72b..",
			WebURL:    "https://gitlab.example.com/root",
		},
		PlatformKubernetes: &PlatformKubernetes{
			APIURL:            "https://104.197.68.152",
			AuthorizationType: "rbac",
			CaCert:            "-----BEGIN CERTIFICATE-----\r\nAAAAA\r\n-----END CERTIFICATE-----",
		},
		ManagementProject: &ManagementProject{
			ID:                2,
			Description:       "skjdfgsdfg",
			Name:              "project2",
			NameWithNamespace: "John Doe8 / project2",
			Path:              "project2",
			PathWithNamespace: "namespace2/project2",
			CreatedAt:         mustParseTime("2019-10-11T02:55:54.138Z"),
		},
		Group: &Group{
			ID:     26,
			Name:   "group-with-clusters-api",
			WebURL: "https://gitlab.example.com/group-with-clusters-api",
		},
	}

	assert.Equal(t, want, cluster)
}

func TestAddGroupCluster(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	mux.HandleFunc("/api/v4/groups/26/clusters/user", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPost)
		fmt.Fprintf(w, `{
			"id":24,
			"name":"cluster-5",
			"created_at":"2019-01-03T21:53:40.610Z",
			"managed": true,
			"enabled": true,
			"provider_type":"user",
			"platform_type":"kubernetes",
			"environment_scope":"*",
			"cluster_type":"group_type",
			"user": {
			  "id":1,
			  "name":"Administrator",
			  "username":"root",
			  "state":"active",
			  "avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..",
			  "web_url":"https://gitlab.example.com/root"
			},
			"platform_kubernetes": {
			  "api_url":"https://35.111.51.20",
			  "authorization_type":"rbac",
			  "ca_cert":"-----BEGIN CERTIFICATE-----\r\nAAAAA\r\n-----END CERTIFICATE-----"
			},
			"management_project": null,
			"group": {
			  "id":26,
			  "name":"group-with-clusters-api",
			  "web_url":"https://gitlab.example.com/root/group-with-clusters-api"
			}
		}`)
	})

	cluster, _, err := client.GroupCluster.AddCluster(26, &AddGroupClusterOptions{})
	require.NoError(t, err)

	want := &GroupCluster{
		ID:               24,
		Name:             "cluster-5",
		CreatedAt:        mustParseTime("2019-01-03T21:53:40.610Z"),
		Managed:          true,
		Enabled:          true,
		ProviderType:     "user",
		PlatformType:     "kubernetes",
		EnvironmentScope: "*",
		ClusterType:      "group_type",
		User: &User{
			ID:        1,
			Name:      "Administrator",
			Username:  "root",
			State:     "active",
			AvatarURL: "https://www.gravatar.com/avatar/4249f4df72b..",
			WebURL:    "https://gitlab.example.com/root",
		},
		PlatformKubernetes: &PlatformKubernetes{
			APIURL:            "https://35.111.51.20",
			AuthorizationType: "rbac",
			CaCert:            "-----BEGIN CERTIFICATE-----\r\nAAAAA\r\n-----END CERTIFICATE-----",
		},
		ManagementProject: nil,
		Group: &Group{
			ID:     26,
			Name:   "group-with-clusters-api",
			WebURL: "https://gitlab.example.com/root/group-with-clusters-api",
		},
	}

	assert.Equal(t, want, cluster)
}

func TestEditGroupCluster(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	mux.HandleFunc("/api/v4/groups/26/clusters/24", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPut)
		fmt.Fprintf(w, `{
			"id":24,
			"name":"new-cluster-name",
			"domain":"new-domain.com",
			"created_at":"2019-01-03T21:53:40.610Z",
			"managed": true,
			"enabled": true,
			"provider_type":"user",
			"platform_type":"kubernetes",
			"environment_scope":"*",
			"cluster_type":"group_type",
			"user": {
				"id":1,
				"name":"Administrator",
				"username":"root",
				"state":"active",
				"avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..",
				"web_url":"https://gitlab.example.com/root"
			},
			"platform_kubernetes": {
				"api_url":"https://new-api-url.com",
				"authorization_type":"rbac"
			},
			"management_project": {
				"id":2,
				"description":"sjdkfngjkdsfngdfgndfg",
				"name":"project2",
				"name_with_namespace":"John Doe8 / project2",
				"path":"project2",
				"path_with_namespace":"namespace2/project2",
				"created_at":"2019-10-11T02:55:54.138Z"
			},
			"group": {
				"id":26,
				"name":"group-with-clusters-api",
				"web_url":"https://gitlab.example.com/group-with-clusters-api"
			}
		}`)
	})

	name := "new-cluster-name"
	domain := "new-domain.com"
	environmentScope := "*"
	apiURL := "https://new-api-url.com"

	opt := &EditGroupClusterOptions{
		Name:             &name,
		Domain:           &domain,
		EnvironmentScope: &environmentScope,
		PlatformKubernetes: &EditGroupPlatformKubernetesOptions{
			APIURL: &apiURL,
		},
	}

	cluster, _, err := client.GroupCluster.EditCluster(26, 24, opt)
	require.NoError(t, err, "GroupCluster.EditCluster should not return an error")
	require.NotNil(t, cluster, "Cluster response should not be nil")

	want := &GroupCluster{
		ID:               24,
		Name:             "new-cluster-name",
		Domain:           "new-domain.com",
		CreatedAt:        mustParseTime("2019-01-03T21:53:40.610Z"),
		Managed:          true,
		Enabled:          true,
		ProviderType:     "user",
		PlatformType:     "kubernetes",
		EnvironmentScope: "*",
		ClusterType:      "group_type",
		User: &User{
			ID:        1,
			Name:      "Administrator",
			Username:  "root",
			State:     "active",
			AvatarURL: "https://www.gravatar.com/avatar/4249f4df72b..",
			WebURL:    "https://gitlab.example.com/root",
		},
		PlatformKubernetes: &PlatformKubernetes{
			APIURL:            "https://new-api-url.com",
			AuthorizationType: "rbac",
		},
		ManagementProject: &ManagementProject{
			ID:                2,
			Description:       "sjdkfngjkdsfngdfgndfg",
			Name:              "project2",
			NameWithNamespace: "John Doe8 / project2",
			Path:              "project2",
			PathWithNamespace: "namespace2/project2",
			CreatedAt:         mustParseTime("2019-10-11T02:55:54.138Z"),
		},
		Group: &Group{
			ID:     26,
			Name:   "group-with-clusters-api",
			WebURL: "https://gitlab.example.com/group-with-clusters-api",
		},
	}

	assert.Equal(t, want, cluster, "GroupCluster.EditCluster returned unexpected result")
}

func TestDeleteGroupCluster(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	mux.HandleFunc("/api/v4/groups/26/clusters/23", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodDelete)
	})

	_, err := client.GroupCluster.DeleteCluster(26, 23)
	require.NoError(t, err, "GroupCluster.DeleteCluster should not return an error")
}
