package collectors

import (
	"context"

	"github.com/go-logr/logr"
	"github.com/prometheus/client_golang/prometheus"
	"sigs.k8s.io/controller-runtime/pkg/client"

	"github.com/tidbcloud/infra-provider/pkg/consts"
	"github.com/tidbcloud/infra-provider/regional-server/api/v1alpha1"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/common/utils"
)

var (
	vpcpeeringInfo = prometheus.NewDesc(
		"regional_server_vpcpeering_info",
		"Information about vpcpeering CR.",
		[]string{
			"name",
			"source_vpc",
			"target_vpc",
			"target_account",
			"target_cidr",
			"tenant_id",
			"project_id",
			"region",
			"provider",
			"status",
		}, nil)
)

type vpcpeering struct {
	cli client.Client
	log logr.Logger
}

var _ prometheus.Collector = &vpcpeering{}

func (a *vpcpeering) Describe(ch chan<- *prometheus.Desc) {
	ch <- vpcpeeringInfo
}

func (a *vpcpeering) Collect(ch chan<- prometheus.Metric) {
	vpcpeeringList := &v1alpha1.VPCPeeringList{}
	err := a.cli.List(context.Background(), vpcpeeringList)
	if err != nil {
		a.log.Error(err, "fetching vpcpeerings")
		return
	}

	for _, vpcpeeringCR := range vpcpeeringList.Items {

		var sourceVPC, targetAccount, targetCIDR, targetVPC string
		if vpcpeeringCR.Spec.SourceVPCRef != nil {
			sourceVPC = vpcpeeringCR.Spec.SourceVPCRef.Name
		}
		switch vpcpeeringCR.Spec.Provider {
		case consts.ProviderTypeEKS:
			if vpcpeeringCR.Spec.Target.AWS != nil {
				targetAccount = vpcpeeringCR.Spec.Target.AWS.AccountID
				targetCIDR = vpcpeeringCR.Spec.Target.AWS.PeerCIDR
				targetVPC = vpcpeeringCR.Spec.Target.AWS.VpcID
			}
		case consts.ProviderTypeGKE:
			if vpcpeeringCR.Spec.Target.GCP != nil {
				targetAccount = vpcpeeringCR.Spec.Target.GCP.ProjectID
				targetCIDR = vpcpeeringCR.Spec.Target.GCP.PeerCIDR
				targetVPC = vpcpeeringCR.Spec.Target.GCP.PeerNetwork
			}
		}
		if vpcpeeringCR.Spec.Target.TargetVPC != nil {
			targetVPC = vpcpeeringCR.Spec.Target.TargetVPC.Name
		}

		var tenant, project string
		tenants, projects := utils.GetRelatedTenantProjects(vpcpeeringCR.GetLabels())
		if len(tenants) == 1 && len(projects) == 1 {
			tenant = tenants[0]
			project = projects[0]
		}

		ch <- prometheus.MustNewConstMetric(
			vpcpeeringInfo,
			prometheus.GaugeValue,
			1.0,
			vpcpeeringCR.Name,
			sourceVPC,
			targetAccount,
			targetVPC,
			targetCIDR,
			tenant,
			project,
			vpcpeeringCR.Spec.Region,
			vpcpeeringCR.Spec.Provider,
			string(vpcpeeringCR.Status.Phase),
		)
	}
}
