package avatar

import (
	"context"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/suyuan32/simple-admin-common/msg/errormsg"
	"time"

	"wechat-api/internal/svc"
	"wechat-api/internal/types"

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

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

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

func (l *GetSignatureResponseLogic) GetSignatureResponse() (resp *types.AvatarSignatureResp, err error) {
	userId := l.ctx.Value("userId").(uint64)
	helper := NewMpUploadOssHelper(l.svcCtx.Config.Aliyun.ACCESS_KEY_ID, l.svcCtx.Config.Aliyun.ACCESS_KEY_SECRET, 1, 10)
	params := helper.CreateUploadParams()
	OSSAccessKeyId := params["OSSAccessKeyId"]
	policy := params["policy"]
	signature := params["signature"]
	key := fmt.Sprintf("mini_program/qingmasiyuai/avatar/%d.jpg", userId)
	return &types.AvatarSignatureResp{
		BaseDataInfo: types.BaseDataInfo{
			Code: 0,
			Msg:  errormsg.Success,
		},
		Data: types.SignatureInfo{
			Key:            &key,
			OSSAccessKeyId: &OSSAccessKeyId,
			Policy:         &policy,
			Signature:      &signature,
		},
	}, nil
}

type MpUploadOssHelper struct {
	AccessKeyId     string
	AccessKeySecret string
	Timeout         int
	MaxSize         int
}

type Policy struct {
	Expiration string          `json:"expiration"`
	Conditions [][]interface{} `json:"conditions"`
}

func NewMpUploadOssHelper(accessKeyId, accessKeySecret string, timeout, maxSize int) *MpUploadOssHelper {
	if timeout == 0 {
		timeout = 1
	}
	if maxSize == 0 {
		maxSize = 10
	}
	return &MpUploadOssHelper{
		AccessKeyId:     accessKeyId,
		AccessKeySecret: accessKeySecret,
		Timeout:         timeout,
		MaxSize:         maxSize,
	}
}

func (helper *MpUploadOssHelper) CreateUploadParams() map[string]string {
	policy := helper.getPolicyBase64()
	signature := helper.signature(policy)
	return map[string]string{
		"OSSAccessKeyId": helper.AccessKeyId,
		"policy":         policy,
		"signature":      signature,
	}
}

func (helper *MpUploadOssHelper) getPolicyBase64() string {
	expiration := time.Now().Add(time.Duration(helper.Timeout) * time.Hour).UTC().Format(time.RFC3339)
	policy := Policy{
		Expiration: expiration,
		Conditions: [][]interface{}{
			{"content-length-range", 0, helper.MaxSize * 1024 * 1024},
		},
	}
	policyBytes, _ := json.Marshal(policy)
	return base64.StdEncoding.EncodeToString(policyBytes)
}

func (helper *MpUploadOssHelper) signature(policy string) string {
	h := hmac.New(sha1.New, []byte(helper.AccessKeySecret))
	h.Write([]byte(policy))
	return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
