package oss

import (
	"bytes"
	"io"
	"os"
	"strings"
	"time"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

var bucket *oss.Bucket

var ProjectRoot = "webserver"

// InitOSSClient 初始化OSS鉴权客户端
func Init() error {
	client, err := oss.New(os.Getenv("OSS_END_POINT"), os.Getenv("OSS_ACCESS_KEY_ID"), os.Getenv("OSS_ACCESS_KEY_SECRET"))
	if err != nil {
		panic("创建oss.Client失败")
	}

	// 获取存储空间。
	obucket, err := client.Bucket(os.Getenv("OSS_BUCKET"))
	if err != nil {
		panic("创建oss.Bucket失败")
	}
	bucket = obucket

	if os.Getenv("ENV_VALUE") == "test" {
		ProjectRoot = "testserver"
	}

	if os.Getenv("ENV_VALUE") == "dev" {
		ProjectRoot = "devserver"
	}

	return nil
}

func GetBucket() *oss.Bucket {
	return bucket
}

// Put 将文件流保存到指定目录
func Put(file io.Reader, dst string) error {
	// 凭证有效期
	credentialTTL := 3600

	// 是否允许覆盖
	overwrite := true

	options := []oss.Option{
		oss.Expires(time.Now().Add(time.Duration(credentialTTL) * time.Second)),
		oss.ForbidOverWrite(!overwrite),
	}
	// 上传文件
	err := bucket.PutObject(dst, file, options...)
	if err != nil {
		return err
	}

	return nil
}

// Get 读取文件
func Get(dst string) (*bytes.Buffer, error) {
	// 下载文件到缓存。
	body, err := bucket.GetObject(dst)
	if err != nil {
		return nil, err
	}
	defer body.Close()

	buf := new(bytes.Buffer)
	io.Copy(buf, body)
	return buf, nil
}

func Delete(dst []string, options ...oss.Option) (oss.DeleteObjectsResult, error) {
	// 将oss.DeleteObjectsQuiet设置为true，表示不返回删除结果。
	res, err := bucket.DeleteObjects(dst, options...)
	if err != nil {
		return res, err
	}
	return res, nil
}

func DeleteBatch(path string) error {
	marker := oss.Marker("")
	// 如果您需要删除所有前缀为src的文件，则prefix设置为src。设置为src后，所有前缀为src的非目录文件、src目录以及目录下的所有文件均会被删除。
	//prefix := oss.Prefix("src")
	// 如果您仅需要删除src目录及目录下的所有文件，则prefix设置为src/。
	dst := path
	if path[len(path)-1] != '/' {
		dst = dst + "/"
	}
	prefix := oss.Prefix(dst)
	lor, err := bucket.ListObjects(marker, prefix)
	if err != nil {
		return err
	}

	objects := []string{}
	for _, object := range lor.Objects {
		objects = append(objects, object.Key)
	}
	// 将oss.DeleteObjectsQuiet设置为true，表示不返回删除结果。
	_, err = Delete(objects, oss.DeleteObjectsQuiet(true))
	if err != nil {
		return err
	}

	return nil
}

func SignVideoImageURL(path string, style string) string {
	path = strings.Replace(path, "http://idouwebmodels.oss-cn-hangzhou.aliyuncs.com/", "", 1)
	options := []oss.Option{}
	if style != "" {
		options = append(options, oss.Process(style))
	}
	signedGetURL, _ := bucket.SignURL(path, oss.HTTPGet, 600, options...)
	return signedGetURL
}

func SignVideoImageURLExpire(path string, style string, expire int64) string {
	path = strings.Replace(path, "http://idouwebmodels.oss-cn-hangzhou.aliyuncs.com/", "", 1)
	options := []oss.Option{}
	if style != "" {
		options = append(options, oss.Process(style))
	}
	signedGetURL, _ := bucket.SignURL(path, oss.HTTPGet, expire, options...)
	return signedGetURL
}

// AssetsPreviewImageURL 资产缩略图地址
func SignSourceUrl(path string) string {
	return path
	// 移除 http://idouwebmodels.oss-cn-hangzhou.aliyuncs.com/ 前缀
	path = strings.Replace(path, "http://idouwebmodels.oss-cn-hangzhou.aliyuncs.com/", "", 1)
	signedGetURL, _ := bucket.SignURL(path, oss.HTTPGet, 600)
	return signedGetURL
}

// SignSourceUrlBatch 资产效果图地址
func SignSourceUrlBatch(path string) []string {
	if path == "" {
		return []string{}
	}
	pathList := strings.Split(path, ",")
	return pathList
	signedGetURL := make([]string, 0, len(pathList))
	if !(len(pathList) == 0 || pathList[0] == "") {
		for _, v := range pathList {
			// 移除 http://idouwebmodels.oss-cn-hangzhou.aliyuncs.com/ 前缀
			v = strings.Replace(v, "http://idouwebmodels.oss-cn-hangzhou.aliyuncs.com/", "", 1)
			url, _ := bucket.SignURL(v, oss.HTTPGet, 600)
			signedGetURL = append(signedGetURL, url)
		}
	}

	return signedGetURL
}

func GetFolderSize(folderPath string) (int64, error) {
	dst := folderPath
	if folderPath[len(folderPath)-1] != '/' {
		dst = dst + "/"
	}

	var totalSize int64
	// 获取指定目录下的所有文件
	marker := oss.Marker("")

	for {
		listObjectsResult, err := bucket.ListObjects(marker, oss.Prefix(dst))
		if err != nil {
			return 0, err
		}

		// 累加文件大小
		for _, object := range listObjectsResult.Objects {
			totalSize += object.Size
		}

		// 遍历子目录
		for _, commonPrefix := range listObjectsResult.CommonPrefixes {
			subFolderName := commonPrefix[len(folderPath):]
			subFolderSize, err := GetFolderSize(subFolderName)
			if err != nil {
				return 0, err
			}
			totalSize += subFolderSize
		}

		// 判断是否还有更多文件需要获取
		if !listObjectsResult.IsTruncated {
			break
		}

		marker = oss.Marker(listObjectsResult.NextMarker)
	}

	return totalSize, nil
}
