package account

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/pingcap/log"
	regionalapiv1 "github.com/tidbcloud/infra-provider/api/tidbcloud/regional-server/v1"
	bizerr "github.com/tidbcloud/infra-provider/regional-server/pkg/common/errors"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/common/message"
	rsconfig "github.com/tidbcloud/infra-provider/regional-server/pkg/config"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/resourcemanager/account"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/resourcemanager/vpc"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/router/interceptor"
	svcaccount "github.com/tidbcloud/infra-provider/regional-server/pkg/service/account"
	"go.uber.org/zap"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

type AccountHandler struct {
	accountsvc *svcaccount.Service
	config     rsconfig.RootConfig
}

func NewAccountHandler(cli client.Client, config rsconfig.RootConfig) *AccountHandler {
	return &AccountHandler{
		accountsvc: svcaccount.NewService(account.NewAccountReaderWriter(cli, config), vpc.NewVPCReader(cli), config),
		config:     config,
	}
}

func (r *AccountHandler) PreAssignAccount(c *gin.Context) {
	req := &regionalapiv1.AssignAccountRequest{}
	if ok := interceptor.HandleJsonPbRequestFromBody(c, req); !ok {
		return
	}
	if err := (&message.AssignAccountReqValidatable{AssignAccountRequest: req}).Validate(); err != nil {
		log.Error("invalid request", zap.Error(err))
		interceptor.Fail(c, bizerr.New(bizerr.ParameterInvalid, err.Error()))
		return
	}

	resp, err := r.accountsvc.PreAssignAccount(c, req)
	if err != nil {
		log.Error("failed to pre assign account", zap.Error(err))
		interceptor.Fail(c, err)
	} else {
		interceptor.SucceedPb(c, http.StatusOK, resp)
	}
}

func (r *AccountHandler) GetAccount(c *gin.Context) {
	req := &regionalapiv1.GetAccountRequest{
		ProjectId: c.Query("projectId"),
	}

	if err := (&message.GetAccountReqValidatable{GetAccountRequest: req}).Validate(); err != nil {
		log.Error("invalid request", zap.Error(err))
		interceptor.Fail(c, bizerr.New(bizerr.ParameterInvalid, err.Error()))
		return
	}

	resp, err := r.accountsvc.GetAccount(c, req)
	if err != nil {
		log.Error("failed to get account", zap.Error(err))
		interceptor.Fail(c, err)
	} else {
		interceptor.SucceedPb(c, http.StatusOK, resp)
	}
}
