package installer

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	corev1 "k8s.io/api/core/v1"
	"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"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

type NamespaceCreator interface {
	Create(name string) error
}

type ZoneInfo struct {
	Zone    string
	Records string
}

type ZoneStatusFetcher interface {
	Fetch(addr string) (string, error)
}

type noOpNamespaceCreator struct{}

func (n *noOpNamespaceCreator) Create(name string) error {
	return nil
}

func NewNoOpNamespaceCreator() NamespaceCreator {
	return &noOpNamespaceCreator{}
}

type realNamespaceCreator struct {
	clientset *kubernetes.Clientset
}

func (n *realNamespaceCreator) Create(name string) error {
	_, err := n.clientset.CoreV1().Namespaces().Create(context.Background(), &corev1.Namespace{
		TypeMeta: metav1.TypeMeta{
			Kind:       " ",
			APIVersion: "",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
		},
	}, metav1.CreateOptions{})
	if err != nil && errors.IsAlreadyExists(err) {
		return nil
	}
	return err
}

// TODO(gio): take http client
type realZoneStatusFetcher struct{}

func (f *realZoneStatusFetcher) Fetch(addr string) (string, error) {
	fmt.Printf("--- %s\n", addr)
	resp, err := http.Get(addr)
	if err != nil {
		return "", err
	}
	var buf bytes.Buffer
	if _, err := io.Copy(&buf, resp.Body); err != nil {
		return "", err
	}
	return buf.String(), nil
}

func NewNamespaceCreator(kubeconfig string) (NamespaceCreator, error) {
	clientset, err := NewKubeConfig(kubeconfig)
	if err != nil {
		return nil, err
	}
	return &realNamespaceCreator{clientset}, nil
}

func NewZoneStatusFetcher(kubeconfig string) (ZoneStatusFetcher, error) {
	return &realZoneStatusFetcher{}, nil
}

type HelmReleaseMonitor interface {
	IsReleased(namespace, name string) (bool, error)
}

type realHelmReleaseMonitor struct {
	d dynamic.Interface
}

func (m *realHelmReleaseMonitor) IsReleased(namespace, name string) (bool, error) {
	ctx := context.Background()
	res, err := m.d.Resource(schema.GroupVersionResource{"helm.toolkit.fluxcd.io", "v2beta1", "helmreleases"}).Namespace(namespace).Get(ctx, name, metav1.GetOptions{})
	if err != nil {
		return false, err
	}
	b, err := res.MarshalJSON()
	if err != nil {
		return false, err
	}
	var hr helmRelease
	if err := json.Unmarshal(b, &hr); err != nil {
		return false, err
	}
	for _, c := range hr.Status.Conditions {
		if c.Type == "Ready" && c.Status == "True" {
			return true, nil
		}
	}
	return false, nil
}

func NewHelmReleaseMonitor(kubeconfig string) (HelmReleaseMonitor, error) {
	c, err := NewKubeConfig(kubeconfig)
	if err != nil {
		return nil, err
	}
	d := dynamic.New(c.RESTClient())
	return &realHelmReleaseMonitor{d}, nil
}

func NewKubeConfig(kubeconfig string) (*kubernetes.Clientset, error) {
	if kubeconfig == "" {
		config, err := rest.InClusterConfig()
		if err != nil {
			return nil, err
		}
		return kubernetes.NewForConfig(config)

	} else {
		config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
		if err != nil {
			return nil, err
		}
		return kubernetes.NewForConfig(config)
	}
}
