package oss_core

import (
	"context"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"path/filepath"
	"strings"
	"time"

	"github.com/qiniu/go-sdk/v7/auth/qbox"
	"github.com/qiniu/go-sdk/v7/storage"
	"sundynix-micro-go/app/file/rpc/file"
	"sundynix-micro-go/common/utils/hash"
)

type QiniuUploader struct {
	mac    *qbox.Mac
	config *file.StorageConfigInfo
}

func NewQiniuUploader(conf *file.StorageConfigInfo) (Uploader, error) {
	mac := qbox.NewMac(conf.AccessKeyId, conf.AccessKeySecret)
	return &QiniuUploader{
		mac:    mac,
		config: conf,
	}, nil
}

func (q *QiniuUploader) UploadFile(ctx context.Context, file multipart.File, fileHeader *multipart.FileHeader) (string, string, error) {
	ext := filepath.Ext(fileHeader.Filename)
	filename := hash.MD5([]byte(strings.TrimSuffix(fileHeader.Filename, ext))) + ext
	timestr := fmt.Sprintf("%d", time.Now().UnixMicro())
	objectKey := time.Now().Format("2006-01-02") + "/" + timestr + "-" + filename

	putPolicy := storage.PutPolicy{
		Scope: q.config.BucketName,
	}
	upToken := putPolicy.UploadToken(q.mac)

	cfg := storage.Config{}
	// 根据配置中的 Region 判断
	// 这里简单写死，如果要自适应可以根据 config.Region 给定
	cfg.Zone = &storage.ZoneHuadong
	cfg.UseHTTPS = false
	cfg.UseCdnDomains = false

	formUploader := storage.NewFormUploader(&cfg)
	ret := storage.PutRet{}

	err := formUploader.Put(ctx, &ret, upToken, objectKey, file, fileHeader.Size, nil)
	if err != nil {
		return "", "", fmt.Errorf("上传七牛云失败: %v", err)
	}

	url := q.config.BucketUrl + "/" + ret.Key
	return url, ret.Key, nil
}

func (q *QiniuUploader) DeleteFile(ctx context.Context, key string) error {
	cfg := storage.Config{}
	cfg.Zone = &storage.ZoneHuadong
	bucketManager := storage.NewBucketManager(q.mac, &cfg)
	return bucketManager.Delete(q.config.BucketName, key)
}

func (q *QiniuUploader) DownloadFile(ctx context.Context, key string) (io.ReadCloser, error) {
	mac := qbox.NewMac(q.config.AccessKeyId, q.config.AccessKeySecret)
	domain := q.config.BucketUrl
	deadline := time.Now().Add(time.Second * 3600).Unix() // 1小时有效期
	privateAccessURL := storage.MakePrivateURL(mac, domain, key, deadline)

	resp, err := http.Get(privateAccessURL)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		resp.Body.Close()
		return nil, fmt.Errorf("qiniu download failed with status: %s", resp.Status)
	}
	return resp.Body, nil
}
