package status

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/giolekva/pcloud/core/installer/kube"

	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/dynamic"
)

type HelmRelease struct {
	Metadata Metadata `json:"metadata"`
	Status   struct {
		Conditions []struct {
			Type   string `json:"type"`
			Status string `json:"status"`
		} `json:"conditions"`
	} `json:"status,omitempty"`
}

type helmReleaseMonitor struct {
	d dynamic.Interface
}

func (m *helmReleaseMonitor) Get(ref ResourceRef) (Status, error) {
	ctx := context.Background()
	res, err := m.d.Resource(
		schema.GroupVersionResource{
			Group:    "helm.toolkit.fluxcd.io",
			Version:  "v2beta1",
			Resource: "helmreleases",
		},
	).Namespace(ref.Namespace).Get(ctx, ref.Name, metav1.GetOptions{})
	if err != nil {
		if errors.IsNotFound(err) {
			return StatusNotFound, nil
		}
		return StatusNoStatus, err
	}
	b, err := res.MarshalJSON()
	if err != nil {
		return StatusNoStatus, err
	}
	var hr HelmRelease
	if err := json.Unmarshal(b, &hr); err != nil {
		return StatusNoStatus, err
	}
	id, ok := hr.Metadata.Annotations["dodo.cloud/id"]
	if !ok {
		fmt.Printf("## missing dodo.cloud/id: %+v\n", ref)
		return StatusNoStatus, nil
	}
	if id != ref.Id {
		return StatusNotFound, nil
	}
	// TODO(gio): check more thoroughly
	for _, c := range hr.Status.Conditions {
		if c.Type == "Ready" && c.Status == "True" {
			return StatusSuccess, nil
		}
	}
	return StatusProcessing, nil
}

func NewHelmReleaseMonitor(kubeconfig string) (ResourceMonitor, error) {
	c, err := kube.NewKubeClient(kube.KubeConfigOpts{KubeConfigPath: kubeconfig})
	if err != nil {
		return nil, err
	}
	d := dynamic.New(c.RESTClient())
	return &helmReleaseMonitor{d}, nil
}
