package resources

import (
	"encoding/json"
	"strconv"

	"github.com/crossplane-contrib/provider-aws/apis/eks/manualv1alpha1"
	commonv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
	"github.com/prometheus/client_golang/prometheus"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime/schema"

	"github.com/tidbcloud/eks-provider/infra-exporter/utils"
)

var (
	nodegroupGVR = schema.GroupVersionResource{
		Group:    "eks.aws.crossplane.io",
		Version:  "v1alpha1",
		Resource: "nodegroups",
	}

	nodegroupInfo = prometheus.NewDesc(
		prometheus.BuildFQName("infra", "exporter", "nodegroup"),
		"Information about nodegroup CR.",
		[]string{
			"name",
			"network",
			"namespace",
			"cluster",
			"component",
			"zone",
			"delete_timestamp",
			"desired_version",
			"desired_size",
			"actual_version",
			"status",
			"ready",
			"synced",
		}, nil)
)

type nodegroup struct {
	defaultResource
}

var _ Interface = &nodegroup{}

func (n nodegroup) HasDedicatedLabel() bool {
	return false
}

func (n nodegroup) GVR() schema.GroupVersionResource {
	return nodegroupGVR
}

func (n nodegroup) Desc() *prometheus.Desc {
	return nodegroupInfo
}

func (n nodegroup) FilterOut(obj *unstructured.Unstructured) bool {
	// Filter out shared-vpc nodegroups
	return utils.IsSharedVPC(obj)
}

func (n nodegroup) Extract(obj *unstructured.Unstructured) prometheus.Metric {
	bytes, _ := obj.MarshalJSON()

	var ng manualv1alpha1.NodeGroup
	_ = json.Unmarshal(bytes, &ng)

	var deleteTS, ready, synced string
	if !ng.DeletionTimestamp.IsZero() {
		deleteTS = ng.DeletionTimestamp.String()
	}

	for _, c := range ng.Status.Conditions {
		if c.Type == commonv1.TypeReady {
			ready = string(c.Status)
		}
		if c.Type == commonv1.TypeSynced {
			synced = string(c.Status)
		}
	}

	return prometheus.MustNewConstMetric(
		nodegroupInfo,
		prometheus.GaugeValue,
		1.0,
		ng.Name,
		ng.Labels["tidbcloud-network"],
		ng.Labels["tidbcloud-namespace"],
		ng.Labels["cluster"],
		ng.Labels["component"],
		ng.Labels["tidbcloud-nodegroup-zones"],
		deleteTS,
		utils.GetReferencedOrDefault(ng.Spec.ForProvider.Version, ""),
		strconv.FormatInt(int64(utils.GetReferencedOrDefault(ng.Status.AtProvider.ScalingConfig.DesiredSize, 0)), 10),
		ng.Status.AtProvider.Version,
		string(ng.Status.AtProvider.Status),
		ready,
		synced,
	)
}
