package resources

import (
	"encoding/json"
	"strconv"

	"github.com/crossplane-contrib/provider-aws/apis/autoscaling/v1beta1"
	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/infra-provider/pkg/nodegroup/selfmanaged"
	"github.com/tidbcloud/infra-provider/pkg/util"

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

var (
	asgGVR = schema.GroupVersionResource{
		Group:    "autoscaling.aws.crossplane.io",
		Version:  "v1beta1",
		Resource: "autoscalinggroups",
	}

	asgInfo = prometheus.NewDesc(
		prometheus.BuildFQName("infra", "exporter", "autoscalinggroup"),
		"Information about autoscaling group CR.",
		[]string{
			"name",
			"network",
			"namespace",
			"cluster",
			"component",
			"zone",
			"delete_timestamp",
			"version",
			"desired_size",
			"ready",
			"synced",
		}, nil)
)

type autoscalinggroup struct {
	defaultResource
}

var _ Interface = &autoscalinggroup{}

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

func (n autoscalinggroup) GVR() schema.GroupVersionResource {
	return asgGVR
}

func (n autoscalinggroup) Desc() *prometheus.Desc {
	return asgInfo
}

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

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

	var asg v1beta1.AutoScalingGroup
	_ = json.Unmarshal(bytes, &asg)

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

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

	return prometheus.MustNewConstMetric(
		asgInfo,
		prometheus.GaugeValue,
		1.0,
		asg.Name,
		asg.Labels["tidbcloud-network"],
		asg.Labels["tidbcloud-namespace"],
		asg.Labels["cluster"],
		asg.Labels["component"],
		asg.Labels["tidbcloud-nodegroup-zones"],
		deleteTS,
		util.GetAnnotation(&asg, selfmanaged.K8sVersionAnnotationKey),
		strconv.FormatInt(utils.GetReferencedOrDefault(asg.Spec.ForProvider.DesiredCapacity, 0), 10),
		ready,
		synced,
	)
}
