package v1

import (
	"github.com/gin-gonic/gin"

	"github.com/pingcap-inc/pchub/internal/apiserver/store"
	v1 "github.com/pingcap-inc/pchub/model/v1"
	"github.com/pingcap-inc/pchub/pkg/errors"
	"github.com/pingcap-inc/pchub/pkg/log"
)

type ApprOptionsSrv interface {
	List(c *gin.Context, et string, b *v1.LarkApprOptionsBody) (*v1.LarkApprOptionsRes, error)
}

type apprOptionsService struct {
	store store.Factory
}

var _ ApprOptionsSrv = (*apprOptionsService)(nil)

func newApprOptions(srv *service) *apprOptionsService {
	return &apprOptionsService{store: srv.store}
}

func (apo *apprOptionsService) List(c *gin.Context, et string, b *v1.LarkApprOptionsBody) (*v1.LarkApprOptionsRes, error) {
	log.L(c).Info("ApprOptionsSrv.List called.")

	switch et {
	case "cloud_role":
		return apo.listCloudRole(c, b)
	case "cloud_provider":
		return apo.listProvider(c, b)
	default:
		return nil, errors.New(et + " not supported")
	}
}

func (apo *apprOptionsService) listProvider(c *gin.Context, _ *v1.LarkApprOptionsBody) (*v1.LarkApprOptionsRes, error) {
	log.L(c).Info("ApprOptionsSrv.listProvider called.")

	prs, err := apo.store.CloudProvider().Gets(c)
	if err != nil {
		return nil, err
	}

	ops := make([]v1.ApprOption, 0, len(prs))
	zhmap := make(map[string]string)
	enmap := make(map[string]string)

	for _, pr := range prs {
		if pr.Code != "aws" && pr.Code != "gcp" && pr.Code != "azure" && pr.Code != "azurecn" && pr.Code != "alicloud" { //nolint:goconst // acceptable
			continue
		}
		ops = append(ops, v1.ApprOption{
			ID:    pr.Code,
			Value: pr.Code,
		})

		zhmap[pr.Code] = pr.Name
		enmap[pr.Code] = pr.Name
	}

	i18ns := []v1.I18nResource{
		{
			Locale:    "zh_cn",
			IsDefault: true,
			Texts:     zhmap,
		},
		{
			Locale:    "en_us",
			IsDefault: false,
			Texts:     enmap,
		},
	}

	res := v1.LarkApprOptionsRes{
		Code: 0,
		Msg:  "success!",
		Data: v1.LarkApprOptionsData{
			Result: v1.LarkApprOptionsDataResult{
				Options:       ops,
				I18nResources: i18ns,
			},
		},
	}

	return &res, nil
}

func (apo *apprOptionsService) listCloudRole(c *gin.Context, b *v1.LarkApprOptionsBody) (*v1.LarkApprOptionsRes, error) {
	log.L(c).Info("ApprOptionsSrv.listCloudRole called.")

	pname := b.LinkageParams["provider"]

	crs, err := apo.store.CloudMemberRole().ListByProviderName(c, pname)
	if err != nil {
		return nil, err
	}

	ops := make([]v1.ApprOption, 0, len(crs))
	zhmap := make(map[string]string)
	enmap := make(map[string]string)

	for _, cr := range crs {
		ops = append(ops, v1.ApprOption{
			ID:    cr.Code,
			Value: cr.Code,
		})

		zhmap[cr.Code] = cr.Name
		enmap[cr.Code] = cr.Name
	}

	i18ns := []v1.I18nResource{
		{
			Locale:    "zh_cn",
			IsDefault: true,
			Texts:     zhmap,
		},
		{
			Locale:    "en_us",
			IsDefault: false,
			Texts:     enmap,
		},
	}

	res := v1.LarkApprOptionsRes{
		Code: 0,
		Msg:  "success!",
		Data: v1.LarkApprOptionsData{
			Result: v1.LarkApprOptionsDataResult{
				Options:       ops,
				I18nResources: i18ns,
			},
		},
	}

	return &res, nil
}
