package watch_graph //nolint:staticcheck

import (
	"fmt"

	fluxmetav1 "github.com/fluxcd/pkg/apis/meta"
	helmapi "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/github.com/fluxcd/helm-controller/api"
	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"
	sourceapi "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/github.com/fluxcd/source-controller/api"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/module/kubernetes_api/agentk/watch_graph/vendored/k8s.io/api/core"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

func (vx *wgObject2vertex) collectFluxCDHelmControllerHelmReleaseV2(obj *unstructured.Unstructured) *Error {
	o, err := unstructuredToTyped[helmv2.HelmRelease](obj)
	if err != nil {
		return err
	}

	if o.Spec.Chart != nil {
		func() {
			group := sourceapi.GroupName
			if v := o.Spec.Chart.Spec.SourceRef.APIVersion; v != "" {
				gv, err := schema.ParseGroupVersion(v)
				if err != nil {
					vx.appendObjectProcessingWarning(fmt.Sprintf("unable to parse FluxCD HelmRelease chart template sourceRef.apiVersion %q: %v", o.Spec.Chart.Spec.SourceRef.APIVersion, err))
					return
				}
				group = gv.Group
			}
			vx.setArcTo(group, o.Spec.Chart.Spec.SourceRef.Kind, o.Spec.Chart.Spec.SourceRef.Name, o.Spec.Chart.Spec.SourceRef.Namespace, ArcAttrs{}, ReferenceArcType)
		}()

		if o.Spec.Chart.Spec.Verify != nil && o.Spec.Chart.Spec.Verify.SecretRef != nil {
			vx.setArcToSecret(o.Spec.Chart.Spec.Verify.SecretRef.Name, ArcAttrs{}, ReferenceArcType)
		}
	}

	if o.Spec.ChartRef != nil {
		func() {
			group := sourceapi.GroupName
			if v := o.Spec.ChartRef.APIVersion; v != "" {
				gv, err := schema.ParseGroupVersion(v)
				if err != nil {
					vx.appendObjectProcessingWarning(fmt.Sprintf("unable to parse FluxCD HelmRelease chart reference sourceRef.apiVersion %q: %v", o.Spec.ChartRef.APIVersion, err))
					return
				}
				group = gv.Group
			}
			vx.setArcTo(group, o.Spec.ChartRef.Kind, o.Spec.ChartRef.Name, o.Spec.ChartRef.Namespace, ArcAttrs{}, ReferenceArcType)
		}()
	}

	if o.Spec.KubeConfig != nil {
		if o.Spec.KubeConfig.ConfigMapRef != nil {
			vx.setArcToConfigMap(o.Spec.KubeConfig.ConfigMapRef.Name, ArcAttrs{}, ReferenceArcType)
		}
		if o.Spec.KubeConfig.SecretRef != nil {
			vx.setArcToSecret(o.Spec.KubeConfig.SecretRef.Name, ArcAttrs{}, ReferenceArcType)
		}
	}

	collectEach(o.Spec.DependsOn, ReferenceArcType, func(t *fluxmetav1.NamespacedObjectReference, arcType ArcType) {
		vx.setArcToGKNs(
			helmapi.HelmReleaseGK,
			t.Name,
			t.Namespace,
			ArcAttrs{},
			arcType,
		)
	})

	if o.Spec.DriftDetection != nil {
		collectEach(o.Spec.DriftDetection.Ignore, ReferenceArcType, func(t *helmv2.IgnoreRule, arcType ArcType) {
			if t.Target != nil {
				vx.setArcTo(t.Target.Group, t.Target.Kind, t.Target.Name, t.Target.Namespace, ArcAttrs{}, arcType)
			}
		})
	}

	collectEach(o.Spec.ValuesFrom, ReferenceArcType, func(t *fluxmetav1.ValuesReference, arcType ArcType) {
		switch t.Kind {
		case "Secret":
			vx.setArcToSecret(t.Name, ArcAttrs{}, arcType)
		case "ConfigMap":
			vx.setArcToConfigMap(t.Name, ArcAttrs{}, arcType)
		default:
			vx.appendObjectProcessingWarning(fmt.Sprintf("values from reference in HelmRelease has an unsupported kind %q", t.Kind))
		}
	})

	collectEach(o.Spec.PostRenderers, ReferenceArcType, func(t *helmv2.PostRenderer, arcType ArcType) {
		if t.Kustomize != nil {
			vx.collectFluxCDKustomizePatchesV1Arcs(t.Kustomize.Patches)
		}
	})

	if o.Spec.TargetNamespace != "" {
		vx.setArcToGK(core.NamespaceGK, o.Spec.TargetNamespace, ArcAttrs{}, ReferenceArcType)
	}

	if o.Spec.StorageNamespace != "" {
		vx.setArcToGK(core.NamespaceGK, o.Spec.StorageNamespace, ArcAttrs{}, ReferenceArcType)
	}

	if o.Spec.ServiceAccountName != "" {
		vx.setArcToGK(core.ServiceAccountGK, o.Spec.ServiceAccountName, ArcAttrs{}, ReferenceArcType)
	}

	return nil
}
