package watch_graph //nolint:staticcheck

import (
	helmv2 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/github.com/fluxcd/helm-controller/api/v2"
	kustomizev1 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/github.com/fluxcd/kustomize-controller/api/v1"
	notificationv1 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/github.com/fluxcd/notification-controller/api/v1"
	notificationv1beta3 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/github.com/fluxcd/notification-controller/api/v1beta3"
	sourcev1 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/github.com/fluxcd/source-controller/api/v1"
	appsv1 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/k8s.io/api/apps/v1"
	autoscalingv1 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/k8s.io/api/autoscaling/v1"
	autoscalingv2 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/k8s.io/api/autoscaling/v2"
	batchv1 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/k8s.io/api/batch/v1"
	corev1 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/k8s.io/api/core/v1"
	eventsv1 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/k8s.io/api/events/v1"
	networkingv1 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/k8s.io/api/networking/v1"
	rbacv1 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/k8s.io/api/rbac/v1"
	storagev1 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/k8s.io/api/storage/v1"
	gatewayapiv1 "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/sigs.k8s.io/gateway-api/apis/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime"
)

func (vx *wgObject2vertex) kindSpecificProcessing(obj *unstructured.Unstructured) *Error {
	switch typeMeta(obj) {

	// Core
	case corev1.PodTypeMeta:
		return vx.collectPodV1(obj)
	case corev1.ReplicationControllerTypeMeta:
		return vx.collectReplicationControllerV1(obj)
	case corev1.ServiceAccountTypeMeta:
		return vx.collectServiceAccountV1(obj)
	case corev1.PersistentVolumeClaimTypeMeta:
		return vx.collectPersistentVolumeClaimV1(obj)
	case corev1.PersistentVolumeTypeMeta:
		return vx.collectPersistentVolumeV1(obj)
	case corev1.SecretTypeMeta:
		return vx.collectSecretV1(obj)
	case corev1.ConfigMapTypeMeta:
		return vx.collectConfigMapV1(obj)

	// Events
	case eventsv1.EventTypeMeta:
		return vx.collectEventV1(obj)

	// Apps
	case appsv1.DeploymentTypeMeta:
		return vx.collectDeploymentV1(obj)
	case appsv1.ReplicaSetTypeMeta:
		return vx.collectReplicaSetV1(obj)
	case appsv1.DaemonSetTypeMeta:
		return vx.collectDaemonSetV1(obj)
	case appsv1.StatefulSetTypeMeta:
		return vx.collectStatefulSetV1(obj)

	// RBAC
	case rbacv1.ClusterRoleBindingTypeMeta:
		return vx.collectClusterRoleBindingV1(obj)
	case rbacv1.RoleBindingTypeMeta:
		return vx.collectRoleBindingV1(obj)

	// Batch
	case batchv1.JobTypeMeta:
		return vx.collectJobV1(obj)
	case batchv1.CronJobTypeMeta:
		return vx.collectCronJobV1(obj)

	// Autoscaling
	case autoscalingv1.HorizontalPodAutoscalerTypeMeta:
		return vx.collectHorizontalPodAutoscalerV1(obj)
	case autoscalingv2.HorizontalPodAutoscalerTypeMeta:
		return vx.collectHorizontalPodAutoscalerV2(obj)

	// Networking
	case networkingv1.IngressTypeMeta:
		return vx.collectIngressV1(obj)

	// Gateway API (networking sig)
	case gatewayapiv1.GatewayTypeMeta:
		return vx.collectGatewayV1(obj)
	case gatewayapiv1.GatewayClassTypeMeta:
		return vx.collectGatewayClassV1(obj)
	case gatewayapiv1.HTTPRouteTypeMeta:
		return vx.collectGatewayHTTPRouteV1(obj)
	case gatewayapiv1.GRPCRouteTypeMeta:
		return vx.collectGatewayGRPCRouteV1(obj)

	// Storage
	case storagev1.CSIStorageCapacityTypeMeta:
		return vx.collectCSIStorageCapacityV1(obj)
	case storagev1.VolumeAttachmentTypeMeta:
		return vx.collectVolumeAttachmentV1(obj)

	// FluxCD
	case sourcev1.GitRepositoryTypeMeta:
		return vx.collectFluxCDSourceControllerGitRepositoryV1(obj)
	case sourcev1.OCIRepositoryTypeMeta:
		return vx.collectFluxCDSourceControllerOCIRepositoryV1(obj)
	case sourcev1.HelmRepositoryTypeMeta:
		return vx.collectFluxCDSourceControllerHelmRepositoryV1(obj)
	case sourcev1.HelmChartTypeMeta:
		return vx.collectFluxCDSourceControllerHelmChartV1(obj)
	case sourcev1.BucketTypeMeta:
		return vx.collectFluxCDSourceControllerBucketV1(obj)

	case kustomizev1.KustomizationTypeMeta:
		return vx.collectFluxCDKustomizeControllerKustomizationV1(obj)

	case helmv2.HelmReleaseTypeMeta:
		return vx.collectFluxCDHelmControllerHelmReleaseV2(obj)

	case notificationv1beta3.ProviderTypeMeta:
		return vx.collectFluxCDNotificationControllerProviderV1Beta3(obj)
	case notificationv1beta3.AlertTypeMeta:
		return vx.collectFluxCDNotificationControllerAlertV1Beta3(obj)
	case notificationv1.ReceiverTypeMeta:
		return vx.collectFluxCDNotificationControllerReceiverV1(obj)
	}
	return nil
}

func unstructuredToTyped[T any](obj *unstructured.Unstructured) (*T, *Error) {
	var o T
	err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &o)
	if err != nil {
		return nil, &Error{
			Message: err.Error(),
			Code:    InvalidArgument,
		}
	}
	return &o, nil
}

// no parsing vs GVK
func typeMeta(obj *unstructured.Unstructured) metav1.TypeMeta {
	return metav1.TypeMeta{
		Kind:       obj.GetKind(),
		APIVersion: obj.GetAPIVersion(),
	}
}
