package cloud

import (
	"fmt"
	"github.com/go-resty/resty/v2"
	"github.com/pkg/errors"
	"gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/database"
	"net/http"
	"sync"
)

const CreateContainer = "/cloud/container/create"
const DeleteContainer = "/cloud/container/delete"
const GetContainer = "/cloud/container/get"

type Cloud struct {
	store  *database.CloudStorage
	idAddr sync.Map
}

func New(store *database.CloudStorage, adapterId string) (*Cloud, error) {
	if store == nil {
		return nil, errors.New("store cannot be nil")
	}

	a := &Cloud{
		store: store,
	}

	css, err := store.GetClustersByAdapterId(adapterId)
	if err != nil {
		return nil, fmt.Errorf("failed to get clusters: %w", err)
	}

	for _, info := range css.List {
		a.idAddr.Store(info.Id, info.Server)
	}

	InitClient()
	return a, nil
}

func (c *Cloud) ContainerCreate(platformId string, param *CreateParam) (resp *Resp, err error) {
	addr, ok := c.GetServerAddrById(platformId)
	if !ok {
		return nil, fmt.Errorf("clusterId not found: %s", platformId)
	}
	respErr := &RespErr{}
	_, err = Request(addr+CreateContainer, http.MethodPost, func(req *resty.Request) {
		req.SetQueryParams(map[string]string{
			"pfId": platformId,
		}).SetBody(param).SetError(&respErr).SetResult(&resp)
	})
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *Cloud) ContainerDelete(platformId string, param *DeleteParam) (resp *Resp, err error) {
	addr, ok := c.GetServerAddrById(platformId)
	if !ok {
		return nil, fmt.Errorf("clusterId not found: %s", platformId)
	}
	respErr := &RespErr{}
	_, err = Request(addr+DeleteContainer, http.MethodDelete, func(req *resty.Request) {
		req.SetQueryParams(map[string]string{
			"pfId": platformId,
		}).SetBody(param).SetError(&respErr).SetResult(&resp)
	})
	if err != nil {
		return nil, err
	}
	return
}

func (c *Cloud) ContainerGet(platformId string, param *GetParam) (resp *Resp, err error) {
	addr, ok := c.GetServerAddrById(platformId)
	if !ok {
		return nil, fmt.Errorf("clusterId not found: %s", platformId)
	}
	respErr := &RespErr{}
	_, err = Request(addr+GetContainer, http.MethodGet, func(req *resty.Request) {
		req.SetQueryParams(map[string]string{
			"pfId": platformId,
			"name": param.Name,
		}).SetBody(param).SetError(&respErr).SetResult(&resp)
	})
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *Cloud) GetServerAddrById(id string) (string, bool) {
	val, ok := c.idAddr.Load(id)
	if !ok {
		return "", false
	}
	addr, ok := val.(string)
	if !ok {
		return "", false
	}
	return addr, true
}
