package main

import (
	"log"
	"net/url"
	"strconv"

	restful "github.com/emicklei/go-restful"

	"novit.tech/direktil/local-server/pkg/mime"
	"novit.tech/direktil/pkg/localconfig"
)

var clusterSecretKVs = []string{}

func newClusterSecretKV[T any](name string) KVSecrets[T] {
	clusterSecretKVs = append(clusterSecretKVs, name)
	return KVSecrets[T]{"clusters/" + name}
}

func wsListClusters(req *restful.Request, resp *restful.Response) {
	cfg := wsReadConfig(resp)
	if cfg == nil {
		return
	}

	clusterNames := make([]string, len(cfg.Clusters))
	for i, cluster := range cfg.Clusters {
		clusterNames[i] = cluster.Name
	}

	resp.WriteEntity(clusterNames)
}

func wsReadCluster(req *restful.Request, resp *restful.Response) (cluster *localconfig.Cluster) {
	clusterName := req.PathParameter("cluster-name")

	cfg := wsReadConfig(resp)
	if cfg == nil {
		return
	}

	cluster = cfg.Cluster(clusterName)
	if cluster == nil {
		wsNotFound(resp)
		return
	}

	return
}

func wsCluster(req *restful.Request, resp *restful.Response) {
	cluster := wsReadCluster(req, resp)
	if cluster == nil {
		return
	}

	resp.WriteEntity(cluster)
}

func wsClusterAddons(req *restful.Request, resp *restful.Response) {
	cluster := wsReadCluster(req, resp)
	if cluster == nil {
		return
	}

	if len(cluster.Addons) == 0 {
		log.Printf("cluster %q has no addons defined", cluster.Name)
		wsNotFound(resp)
		return
	}

	cfg := wsReadConfig(resp)
	if cfg == nil {
		return
	}

	sslCfg, err := sslConfigFromLocalConfig(cfg)
	if err != nil {
		wsError(resp, err)
		return
	}

	wsRender(resp, sslCfg, cluster.Addons, cluster)
}

func wsClusterCACert(req *restful.Request, resp *restful.Response) {
	clusterName := req.PathParameter("cluster-name")
	caName := req.PathParameter("ca-name")

	ca, found, err := clusterCAs.Get(clusterName + "/" + caName)
	if err != nil {
		wsError(resp, err)
		return
	}
	if !found {
		wsNotFound(resp)
		return
	}

	resp.Header().Set("Content-Type", mime.CERT)
	resp.Write(ca.Cert)
}

func wsClusterSignedCert(req *restful.Request, resp *restful.Response) {
	clusterName := req.PathParameter("cluster-name")
	caName := req.PathParameter("ca-name")
	name := req.QueryParameter("name")

	kc, found, err := clusterCASignedKeys.Get(clusterName + "/" + caName + "/" + name)
	if err != nil {
		wsError(resp, err)
		return
	}
	if !found {
		wsNotFound(resp)
		return
	}

	resp.AddHeader("Content-Type", mime.CERT)
	resp.AddHeader("Content-Disposition", "attachment; filename="+strconv.Quote(clusterName+"_"+caName+"_"+url.PathEscape(name)+".crt"))
	resp.Write(kc.Cert)
}