package common

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"path"
	"strings"
	"time"

	"bindbox-game/configs"

	cos "github.com/tencentyun/cos-go-sdk-v5"
)

type Service interface {
	UploadImage(ctx context.Context, filename string, reader io.Reader, contentType string) (string, error)
}

type service struct {
	client     *cos.Client
	bucketURL  string
	publicBase string
}

func New() Service {
	cfg := configs.Get()
	bucket := cfg.COS.Bucket
	region := cfg.COS.Region
	base := fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucket, region)
	bu, _ := url.Parse(base)
	client := cos.NewClient(&cos.BaseURL{BucketURL: bu}, &http.Client{
		Transport: &cos.AuthorizationTransport{SecretID: cfg.COS.SecretID, SecretKey: cfg.COS.SecretKey},
	})
	return &service{client: client, bucketURL: base, publicBase: strings.TrimSpace(cfg.COS.BaseURL)}
}

func (s *service) UploadImage(ctx context.Context, filename string, reader io.Reader, contentType string) (string, error) {
	date := time.Now().Format("2006/01/02")
	ext := strings.ToLower(path.Ext(filename))
	if ext == "" {
		ext = ".jpg"
	}
	ct := contentType
	if ct == "" || ct == "application/octet-stream" {
		switch ext {
		case ".jpg", ".jpeg":
			ct = "image/jpeg"
		case ".png":
			ct = "image/png"
		case ".gif":
			ct = "image/gif"
		case ".webp":
			ct = "image/webp"
		case ".bmp":
			ct = "image/bmp"
		default:
			ct = "application/octet-stream"
		}
	}
	key := fmt.Sprintf("images/%s/%d%s", date, time.Now().UnixNano(), ext)
	_, err := s.client.Object.Put(ctx, key, reader, &cos.ObjectPutOptions{
		ObjectPutHeaderOptions: &cos.ObjectPutHeaderOptions{
			ContentType: ct,
		},
		ACLHeaderOptions: &cos.ACLHeaderOptions{
			XCosACL: "public-read",
		},
	})
	if err != nil {
		return "", err
	}
	if s.publicBase != "" {
		return strings.TrimRight(s.publicBase, "/") + "/" + key, nil
	}
	return s.bucketURL + "/" + key, nil
}
