package console

import (
	"encoding/json"
	"fmt"

	"github.com/AlekSi/pointer"
	"github.com/tidbcloud/pkgv2/bizerr"
	"github.com/tidbcloud/pkgv2/db"
	"github.com/tidbcloud/tiinf/errs"
	"github.com/tidbcloud/tiinf/sdk/auditlog"
	"go.uber.org/zap"
)

type BaseController struct {
	trans db.TransProvider
}

func NewBaseController(trans db.TransProvider) *BaseController {
	return &BaseController{
		trans: trans,
	}
}

func (bc *BaseController) ConvertToAuditLogDetail(a interface{}) (auditlog.Details, error) {
	marshal, err := json.Marshal(a)
	if err != nil {
		return nil, err
	}
	details := auditlog.Details{}
	if err = json.Unmarshal(marshal, &details); err != nil {
		return nil, err
	}
	return details, nil
}

func (bc *BaseController) ConvertAuditLogDetailErrMsg(vv error) *string {
	if vv == nil {
		return nil
	}

	if bz, ok := vv.(bizerr.BizError); ok {
		return pointer.To(fmt.Sprintf("%d, %s", bz.ErrCode(), bz.ErrMsg()))
	} else if te, ok := errs.AsTiError(vv); ok {
		return pointer.To(fmt.Sprintf("%d, %s", te.BizCode(), te.ErrMsg()))
	} else {
		return pointer.To(fmt.Sprintf("%s", vv))
	}
}

func (bc *BaseController) logError(logger *zap.Logger, err bizerr.BizError, msg string) {
	if bizerr.IsInternalErr(err.ErrCode()) {
		logger.Error(msg, zap.Error(err))
	} else if bizerr.IsRequestErr(err.ErrCode()) {
		logger.Warn(msg, zap.Error(err))
	} else if bizerr.IsBusinessErr(err.ErrCode()) {
		// TODO: distinguish warn level or error level
		logger.Warn(msg, zap.Error(err))
	} else {
		logger.Error(msg, zap.Error(err))
	}
}
