package resources

import (
	"encoding/json"

	commonv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/upbound/provider-azure/apis/containerservice/v1beta1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime/schema"

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

var (
	aksGVR = schema.GroupVersionResource{
		Group:    "containerservice.azure.upbound.io",
		Version:  "v1beta2",
		Resource: "kubernetesclusters",
	}

	aksInfo = prometheus.NewDesc(
		prometheus.BuildFQName("infra", "exporter", "aks"),
		"Information about aks CR.",
		[]string{
			"name",
			"desired_version",
			"actual_version",
			"status",
			"ready",
			"synced",
		}, nil)
)

type aks struct {
	defaultResource
}

var _ Interface = &aks{}

func (r aks) HasDedicatedLabel() bool {
	return false
}

func (r aks) GVR() schema.GroupVersionResource {
	return aksGVR
}

func (r aks) Desc() *prometheus.Desc {
	return aksInfo
}

func (r aks) FilterOut(_ *unstructured.Unstructured) bool {
	return false
}

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

	var cr v1beta1.KubernetesCluster
	_ = json.Unmarshal(bytes, &cr)

	var ready, synced string

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

	return prometheus.MustNewConstMetric(
		aksInfo,
		prometheus.GaugeValue,
		1.0,
		cr.Name,
		utils.GetReferencedOrDefault(cr.Spec.ForProvider.KubernetesVersion, ""),
		utils.GetReferencedOrDefault(cr.Status.AtProvider.CurrentKubernetesVersion, ""),
		"", // TODO: Don't have status field in KubernetesCluster CR for now
		ready,
		synced,
	)
}

// TODO(ideascf): Exporse AKS Nodepool CR
// var (
// 	aksNodepoolGVR = schema.GroupVersionResource{
// 		Group:    "containerservice.azure.upbound.io",
// 		Version:  "v1beta2",
// 		Resource: "kubernetesclusternodepools",
// 	}

// 	aksNodepoolInfo = prometheus.NewDesc(
// 		prometheus.BuildFQName("infra", "exporter", "aks_nodepool"),
// 		"Information about aks nodepool CR.",
// 		[]string{
// 			"name",
// 			"project",
// 			"component",
// 			"cluster",
// 			"vm_size",
// 			"locations",
// 			"delete_timestamp",
// 			"desired_version",
// 			"max_size",
// 			"min_size",
// 			"status",
// 			"ready",
// 			"synced",
// 		}, nil)
// )

// type aksNodepool struct {
// 	defaultResource
// }

// var _ Interface = &aksNodepool{}

// func (n aksNodepool) HasDedicatedLabel() bool {
// 	return false
// }

// func (n aksNodepool) GVR() schema.GroupVersionResource {
// 	return aksNodepoolGVR
// }

// func (n aksNodepool) Desc() *prometheus.Desc {
// 	return aksNodepoolInfo
// }

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

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

// 	var np v1beta1.KubernetesClusterNodePool
// 	_ = json.Unmarshal(bytes, &np)

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

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

// 	return prometheus.MustNewConstMetric(
// 		aksNodepoolInfo,
// 		prometheus.GaugeValue,
// 		1.0,
// 		np.Name,
// 		n.getProjectID(&np),
// 		n.getComponent(&np),
// 		np.Labels[namer.ClusterSelectorKey],
// 		utils.GetReferencedOrDefault(np.Spec.ForProvider.VMSize, ""),
// 		strings.Join(np.Spec.ForProvider.AvailabilityZones, ","),
// 		deleteTS,
// 		utils.GetReferencedOrDefault(np.Spec.ForProvider.Version, ""),
// 		strconv.Itoa(np.Spec.ForProvider.MaxCount),
// 		strconv.Itoa(np.Spec.ForProvider.MinCount),
// 		string(np.Status.AtProvider.Status),
// 		ready,
// 		synced,
// 	)
// }
// func (n aksNodepool) getProjectID(np *v1beta1.KubernetesClusterNodePool) string {
// 	return np.Labels["project"]
// }

// func (n aksNodepool) getComponent(np *v1beta1.KubernetesClusterNodePool) string {
// 	return *np.Spec.ForProvider.NodeLabels[namer.ComponentSelectorKey]
// }
