package api

import (
	"context"
	"fmt"
	"log"
	"mesh/conf"
	"path"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

func createMinioClient(conf *conf.AppConf) *minio.Client {

	endpoint := conf.Minio.Endpoint

	accessKeyID := conf.Minio.AccessKey
	secretAccessKey := conf.Minio.AccessSec
	useSSL := false

	// Initialize minio client object.
	minioClient, err := minio.New(endpoint, &minio.Options{
		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
		Secure: useSSL,
	})
	if err != nil {
		log.Fatalln(err)
		return nil
	}
	return minioClient
}

func MinioCreateUserPolicy(c *gin.Context, apictx *ApiSession) (interface{}, error) {

	body := struct {
		Key string
	}{}
	err := c.ShouldBindJSON(&body)
	if err != nil {
		return nil, NewError("参数解析错误!")
	}
	if len(body.Key) < 1 {
		return nil, NewError("Object Key不能为空")
	}
	// Initialize policy condition config.
	policy := minio.NewPostPolicy()

	// Apply upload policy restrictions:
	policy.SetBucket(apictx.Svc.Conf.Minio.Bucket)

	fkey := body.Key //fmt.Sprintf("u/%s/%s", apictx.User.Parent, body.Key)
	policy.SetKey(fkey)
	policy.SetExpires(time.Now().UTC().Add(time.Second * 600)) // expires in 10 days

	// Only allow 'png' images.
	// policy.SetContentType("image/png")

	// Only allow content size in range 1KB to 1MB.
	policy.SetContentLengthRange(0, 5*1024*1024)

	// Add a user metadata using the key "custom" and value "user"
	// policy.SetUserMetadata("custom", "user")

	client := createMinioClient(apictx.Svc.Conf)
	url, err := client.PresignedPutObject(
		context.Background(), apictx.Svc.Conf.Minio.Bucket, fkey, time.Second*600,
	)
	//_, formdata, err := client.PresignedPostPolicy(context.Background(), policy)

	outUrl := fmt.Sprintf("%s://%s%s?%s", url.Scheme, url.Host, url.Path, url.RawQuery)

	if err != nil {
		return nil, err
	}

	out := map[string]interface{}{
		"uploadUrl": outUrl,
		"url":       fmt.Sprintf("%s/%s/%s", apictx.Svc.Conf.Minio.PubHost, apictx.Svc.Conf.Minio.Bucket, fkey),
		"saveType":  conf.SaveType_Minio,
	}
	return out, nil
}

func MinioUploadFile(client *minio.Client, bucketName string, fpath string, key string) (string, int64) {
	info, err := client.FPutObject(context.Background(), bucketName, key, fpath, minio.PutObjectOptions{})
	fmt.Println(info)
	if err != nil {
		return "", 0
	}
	return info.Key, info.Size
}

func MinioUploadLocalFile(client *minio.Client, bucketName string, fpath string, minioDir string) (string, int64) {

	_, name := path.Split(fpath)
	keyFormat := "%s/%s"
	if strings.HasSuffix(minioDir, "/") {
		keyFormat = "%s%s"
	}
	minioKey := fmt.Sprintf(keyFormat, minioDir, name)

	opts := minio.PutObjectOptions{}

	fpathExt := path.Ext(fpath)
	isGzFile := fpathExt == ".gz"
	if isGzFile {
		opts.ContentType = "text/plain"
		opts.ContentEncoding = "gzip"
	}

	info, err := client.FPutObject(context.Background(), bucketName, minioKey, fpath, opts)
	fmt.Println(info)
	if err != nil {
		info, err = client.FPutObject(context.Background(), bucketName, minioKey, fpath, opts)
		if err != nil {
			return "", 0
		}
	}

	return minioKey, info.Size
}
