/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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 trait

import (
	"context"
	"testing"

	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
	"github.com/apache/camel-k/pkg/util/kubernetes"
	"github.com/apache/camel-k/pkg/util/test"

	"github.com/stretchr/testify/assert"

	monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"

	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestConfigurePrometheusTraitInRightPhaseDoesSucceed(t *testing.T) {
	trait, environment := createNominalPrometheusTest()

	configured, err := trait.Configure(environment)

	assert.Nil(t, err)
	assert.True(t, configured)
}

func TestConfigurePrometheusTraitInWrongPhaseDoesNotSucceed(t *testing.T) {
	trait, environment := createNominalPrometheusTest()
	environment.Integration.Status.Phase = v1.IntegrationPhaseResolvingKit

	configured, err := trait.Configure(environment)

	assert.Nil(t, err)
	assert.False(t, configured)
}

func TestApplyNominalPrometheusTraitDoesSucceed(t *testing.T) {
	trait, environment := createNominalPrometheusTest()

	err := trait.Apply(environment)

	assert.Nil(t, err)

	container := environment.Resources.GetContainerByName(defaultContainerName)
	assert.NotNil(t, container)
	test.EnvVarHasValue(t, container.Env, "AB_PROMETHEUS_PORT", "9779")
	ports := container.Ports
	assert.Len(t, ports, 1)
	assert.Equal(t, "prometheus", ports[0].Name)
	assert.Equal(t, int32(9779), ports[0].ContainerPort)
	assert.Equal(t, corev1.ProtocolTCP, ports[0].Protocol)

	service := environment.Resources.GetService(func(service *corev1.Service) bool {
		return service.Name == "integration-name"
	})
	assert.NotNil(t, service)
	assert.Len(t, service.Spec.Ports, 1)

	serviceMonitor := environment.Resources.GetServiceMonitor(func(service *monitoringv1.ServiceMonitor) bool {
		return service.Name == "integration-name"
	})
	assert.NotNil(t, serviceMonitor)

	assert.Len(t, environment.Integration.Status.Conditions, 1)
	condition := environment.Integration.Status.Conditions[0]
	assert.Equal(t, v1.IntegrationConditionPrometheusAvailable, condition.Type)
	assert.Equal(t, corev1.ConditionTrue, condition.Status)
}

func TestApplyPrometheusTraitWithoutContainerDoesNotSucceed(t *testing.T) {
	trait, environment := createNominalPrometheusTest()
	environment.Resources = kubernetes.NewCollection()

	err := trait.Apply(environment)

	assert.Nil(t, err)

	assert.Len(t, environment.Integration.Status.Conditions, 1)
	condition := environment.Integration.Status.Conditions[0]
	assert.Equal(t, v1.IntegrationConditionPrometheusAvailable, condition.Type)
	assert.Equal(t, corev1.ConditionFalse, condition.Status)
}

func TestApplyPrometheusTraitWithServiceDoesNotSucceed(t *testing.T) {
	trait, environment := createNominalPrometheusTest()
	environment.Resources = kubernetes.NewCollection(
		&appsv1.Deployment{
			Spec: appsv1.DeploymentSpec{
				Template: corev1.PodTemplateSpec{
					Spec: corev1.PodSpec{
						Containers: []corev1.Container{
							{
								Name: defaultContainerName,
							},
						},
					},
				},
			},
		},
		&corev1.Service{
			TypeMeta: metav1.TypeMeta{
				Kind:       "Service",
				APIVersion: "v1",
			},
			ObjectMeta: metav1.ObjectMeta{
				Name:      "service-name",
				Namespace: "namespace",
				Labels: map[string]string{
					"camel.apache.org/integration":  "integration-name",
					"camel.apache.org/service.type": v1.ServiceTypeUser,
				},
			},
			Spec: corev1.ServiceSpec{
				Ports: []corev1.ServicePort{},
				Selector: map[string]string{
					"camel.apache.org/integration": "integration-name",
				},
			},
		})

	err := trait.Apply(environment)

	assert.Nil(t, err)

	assert.Len(t, environment.Integration.Status.Conditions, 1)
	condition := environment.Integration.Status.Conditions[0]
	assert.Equal(t, v1.IntegrationConditionServiceNotAvailableReason, condition.Reason)
	assert.Equal(t, corev1.ConditionFalse, condition.Status)
}

func TestApplyDisabledPrometheusTraitShouldDeactivateJavaAgent(t *testing.T) {
	trait, environment := createNominalPrometheusTest()
	trait.Enabled = new(bool)

	err := trait.Apply(environment)

	assert.Nil(t, err)

	container := environment.Resources.GetContainerByName(defaultContainerName)
	assert.NotNil(t, container)
	test.EnvVarHasValue(t, container.Env, "AB_PROMETHEUS_OFF", "true")
}

func TestPrometheusTraitGetServiceMonitor(t *testing.T) {
	trait, environment := createNominalPrometheusTest()

	serviceMonitor, err := trait.getServiceMonitorFor(environment)

	assert.Nil(t, err)

	assert.NotNil(t, serviceMonitor)
	assert.Equal(t, "ServiceMonitor", serviceMonitor.Kind)
	assert.Equal(t, "monitoring.coreos.com/v1", serviceMonitor.APIVersion)
	assert.Equal(t, "integration-name", serviceMonitor.Name)
	assert.Equal(t, "integration-namespace", serviceMonitor.Namespace)
	assert.Equal(t, "integration-name", serviceMonitor.Labels["camel.apache.org/integration"])
	assert.Equal(t, "integration-name", serviceMonitor.Spec.Selector.MatchLabels["camel.apache.org/integration"])
	assert.Len(t, serviceMonitor.Spec.Endpoints, 1)
	assert.Equal(t, "prometheus", serviceMonitor.Spec.Endpoints[0].Port)
}

func createNominalPrometheusTest() (*prometheusTrait, *Environment) {
	trait := newPrometheusTrait()
	enabled := true
	trait.Enabled = &enabled

	environment := &Environment{
		Catalog: NewCatalog(context.TODO(), nil),
		Integration: &v1.Integration{
			ObjectMeta: metav1.ObjectMeta{
				Namespace: "integration-namespace",
				Name:      "integration-name",
			},
			Status: v1.IntegrationStatus{
				Phase: v1.IntegrationPhaseDeploying,
			},
		},
		Resources: kubernetes.NewCollection(
			&appsv1.Deployment{
				Spec: appsv1.DeploymentSpec{
					Template: corev1.PodTemplateSpec{
						Spec: corev1.PodSpec{
							Containers: []corev1.Container{
								{
									Name: defaultContainerName,
								},
							},
						},
					},
				},
			},
		),
	}

	return trait, environment
}
