package client

import (
	"errors"
	"fmt"

	"coopcloud.tech/abra/pkg/context"
	"coopcloud.tech/abra/pkg/log"
	commandconnPkg "coopcloud.tech/abra/pkg/upstream/commandconn"
	dConfig "github.com/docker/cli/cli/config"
	"github.com/docker/cli/cli/context/docker"
	contextStore "github.com/docker/cli/cli/context/store"
)

type Context = contextStore.Metadata

// CreateContext creates a new Docker context.
func CreateContext(contextName string) error {
	host := fmt.Sprintf("ssh://%s", contextName)

	if err := createContext(contextName, host); err != nil {
		return err
	}

	log.Debugf("created the %s context", contextName)

	return nil
}

// createContext interacts with Docker Context to create a Docker context config
func createContext(name string, host string) error {
	s := context.NewDefaultDockerContextStore()
	contextMetadata := contextStore.Metadata{
		Endpoints: make(map[string]interface{}),
		Name:      name,
	}

	contextTLSData := contextStore.ContextTLSData{
		Endpoints: make(map[string]contextStore.EndpointTLSData),
	}

	dockerEP, dockerTLS, err := commandconnPkg.GetDockerEndpointMetadataAndTLS(host)
	if err != nil {
		return err
	}

	contextMetadata.Endpoints[docker.DockerEndpoint] = dockerEP
	if dockerTLS != nil {
		contextTLSData.Endpoints[docker.DockerEndpoint] = *dockerTLS
	}

	if err := s.CreateOrUpdate(contextMetadata); err != nil {
		return err
	}

	if err := s.ResetTLSMaterial(name, &contextTLSData); err != nil {
		return err
	}

	return nil
}

func DeleteContext(name string) error {
	if name == "default" {
		return errors.New("context 'default' cannot be removed")
	}

	if _, err := GetContext(name); err != nil {
		return err
	}

	cfg := dConfig.LoadDefaultConfigFile(nil)
	cfg.CurrentContext = ""
	if err := cfg.Save(); err != nil {
		return err
	}

	return context.NewDefaultDockerContextStore().Remove(name)
}

func GetContext(contextName string) (contextStore.Metadata, error) {
	ctx, err := context.NewDefaultDockerContextStore().GetMetadata(contextName)
	if err != nil {
		return contextStore.Metadata{}, err
	}

	return ctx, nil
}
