package aliyun

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"encoding/xml"
	"fmt"
	"io"
	"net/http"
	"time"

	"u-desk/internal/oss"
)

// ListBuckets 列出所有存储桶
func ListBuckets(accessKeyID, accessKeySecret, endpoint string) ([]oss.BucketEntry, error) {
	if endpoint == "" {
		endpoint = "oss-cn-hangzhou.aliyuncs.com"
	}
	url := "https://" + endpoint + "/"

	req, _ := http.NewRequest("GET", url, nil)
	date := time.Now().UTC().Format("Mon, 02 Jan 2006 15:04:05 GMT")
	req.Header.Set("Date", date)

	stringToSign := "GET\n\n\n" + date + "\n/"
	signature := sign(accessKeySecret, stringToSign)
	req.Header.Set("Authorization", "OSS "+accessKeyID+":"+signature)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("列举存储桶失败: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return nil, fmt.Errorf("列举存储桶失败: HTTP %d: %s", resp.StatusCode, string(body))
	}

	var result listAllMyBucketsResult
	if err := xml.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("解析存储桶列表失败: %w", err)
	}

	entries := make([]oss.BucketEntry, len(result.Buckets.Bucket))
	for i, b := range result.Buckets.Bucket {
		entries[i] = oss.BucketEntry{
			Name:   b.Name,
			Region: b.Location,
		}
	}
	return entries, nil
}

func sign(secretKey, data string) string {
	mac := hmac.New(sha1.New, []byte(secretKey))
	mac.Write([]byte(data))
	return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}

type listAllMyBucketsResult struct {
	XMLName xml.Name `xml:"ListAllMyBucketsResult"`
	Buckets struct {
		Bucket []bucketEntryXML `xml:"Bucket"`
	} `xml:"Buckets"`
}

type bucketEntryXML struct {
	Name     string `xml:"Name"`
	Location string `xml:"Location"`
}
