package logic

import (
	"fusenapi/utils/auth"
	"fusenapi/utils/basic"
	"fusenapi/utils/check"
	"fusenapi/utils/format"
	"time"

	"context"

	"fusenapi/server/upload/internal/svc"
	"fusenapi/server/upload/internal/types"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/zeromicro/go-zero/core/logx"
)

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

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

func (l *UploadFileFrontendLogic) UploadFileFrontend(req *types.RequestUploadFileFrontend, userinfo *auth.UserInfo) (resp *basic.Response) {
	// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
	// userinfo 传入值时, 一定不为null

	if userinfo.IsOnlooker() {
		return resp.SetStatus(basic.CodeUnAuth)
	}

	var uid int64
	var keytype format.TypeFormatS3KeyName
	if userinfo.IsGuest() {
		uid = userinfo.GuestId
		keytype = format.TypeS3KeyGuest
	} else {
		uid = userinfo.UserId
		keytype = format.TypeS3KeyUser
	}

	l.svcCtx.AwsSession.Config.Region = aws.String("us-west-1")
	svc := s3.New(l.svcCtx.AwsSession)

	if req.FileSize > 1024*1024*500 {
		return resp.SetStatus(basic.CodeS3PutSizeLimitErr)
	}

	if !check.CheckCategory(req.Category) {
		return resp.SetStatus(basic.CodeS3CategoryErr)
	}

	now := time.Now().UTC()
	category := format.TypeCategory(req.Category)
	ObjectKey := aws.String(format.FormatS3KeyName(
		keytype,
		uid,
		now,
		l.svcCtx.Config.Env,
		format.TypeCategory(req.Category),
		req.FileName,
	))

	var bucketName *string
	switch category {
	case format.TCategoryRenderMegre:
		bucketName = basic.TempfileBucketName
	default:
		bucketName = basic.StorageBucketName
	}

	s3req, _ := svc.PutObjectRequest(
		&s3.PutObjectInput{
			Bucket:        bucketName,
			Key:           ObjectKey,
			ContentLength: aws.Int64(req.FileSize),
		},
	)

	uri, err := s3req.Presign(time.Minute * 5)
	if err != nil {
		return resp.SetStatus(basic.CodeS3PutObjectRequestErr)
	}

	return resp.SetStatus(basic.CodeOK, map[string]interface{}{
		"upload_url": uri,
	})
}