package tools

import (
	"context"
	"sync"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/schrodinger/manager/operator/proc"
	"github.com/pingcap/schrodinger/pkg/types"
	"github.com/pingcap/schrodinger/util"
	"k8s.io/client-go/kubernetes"
)

// ToolClient manages tools
type ToolClient struct {
	sync.RWMutex
	k8sCli kubernetes.Interface
	ctl    proc.ProcsController
}

// NewToolsClient returns a tools that manages tools
func NewToolsClient(k8sCli kubernetes.Interface) *ToolClient {
	return &ToolClient{
		k8sCli: k8sCli,
		ctl: proc.ProcsController{
			K8sCli: k8sCli,
		},
	}
}

// CreateAPP creates app
func (c *ToolClient) CreateAPP(ctx context.Context, app *types.APPConfig) error {
	c.Lock()
	defer c.Unlock()

	err := c.checkOrCreateNamespace(app.Namespace)
	if err != nil {
		return errors.Trace(err)
	}

	p := appConfigToProc(app)

	if err = c.ctl.StartProc(ctx, p); err != nil {
		return errors.Trace(err)
	}

	pod, err := util.GetPod(app.Namespace, app.Name, c.k8sCli)
	if err != nil {
		return errors.Trace(err)
	}

	app.Host = pod.Status.PodIP
	for _, c := range pod.Status.ContainerStatuses {
		app.ContainerIDs = append(app.ContainerIDs, c.ContainerID)
	}

	log.Debugf("db addr:%s", app.Host)

	return nil
}

func (c *ToolClient) checkOrCreateNamespace(namespace string) error {
	isExist, err := util.CheckNamespaceIsExist(namespace, c.k8sCli)
	if err != nil {
		return errors.Trace(err)
	}
	if !isExist {
		err = util.CreateK8sNamespace(namespace, c.k8sCli)
		if err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}
