package api_key

import (
	"context"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"github.com/suyuan32/simple-admin-common/msg/errormsg"
	"github.com/zeromicro/go-zero/core/errorx"
	"wechat-api/internal/svc"
	"wechat-api/internal/types"
	"wechat-api/internal/utils/dberrorhandler"

	"github.com/zeromicro/go-zero/core/logx"
)

type CreateApiKeyLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewCreateApiKeyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateApiKeyLogic {
	return &CreateApiKeyLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx}
}

func (l *CreateApiKeyLogic) CreateApiKey(req *types.ApiKeyInfo) (resp *types.BaseMsgResp, err error) {
	organizationId := l.ctx.Value("organizationId").(uint64)
	apiKey, err := GenerateAPIKey("sk-", 32)
	if err != nil {
		return nil, errorx.NewCodeInternalError("Failed to generate API key")
	}

	_, err = l.svcCtx.DB.ApiKey.Create().
		SetTitle(*req.Title).
		SetKey(apiKey).
		SetOrganizationID(organizationId).
		Save(l.ctx)

	if err != nil {
		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
	}
	l.svcCtx.Rds.HSet(l.ctx, "api_key", apiKey, req)
	return &types.BaseMsgResp{Msg: errormsg.CreateSuccess}, nil
}

// GenerateAPIKey generates a random API key with a specified prefix.
func GenerateAPIKey(prefix string, length int) (string, error) {
	randomBytes := make([]byte, length)
	_, err := rand.Read(randomBytes)
	if err != nil {
		return "", err
	}

	// Use base64 to encode the random bytes to a string
	encoded := base64.URLEncoding.EncodeToString(randomBytes)

	// Trim the encoded string to the desired length and prepend the prefix
	apiKey := fmt.Sprintf("%s%s", prefix, encoded[:length])

	return apiKey, nil
}
