package ossdrv

import (
	"os"
	"testing"
)

func getEnvOrSkip(t *testing.T, key string) string {
	t.Helper()
	v := os.Getenv(key)
	if v == "" {
		t.Skipf("跳过：环境变量 %s 未设置", key)
	}
	return v
}

func TestQiniuConnect(t *testing.T) {
	ak := getEnvOrSkip(t, "QINIU_AK")
	sk := getEnvOrSkip(t, "QINIU_SK")

	m := &Manager{}
	err := m.Connect("qiniu", ak, sk, "")
	if err != nil {
		t.Fatalf("七牛云连接失败: %v", err)
	}

	cred, ok := m.accounts.Load("qiniu")
	if !ok {
		t.Fatal("凭据未存储")
	}
	c := cred.(*accountCredentials)
	if c.AccessKey != ak {
		t.Errorf("AccessKey 不匹配: got %s", c.AccessKey)
	}
}

func TestQiniuListBuckets(t *testing.T) {
	ak := getEnvOrSkip(t, "QINIU_AK")
	sk := getEnvOrSkip(t, "QINIU_SK")

	m := &Manager{}
	if err := m.Connect("qiniu", ak, sk, ""); err != nil {
		t.Skipf("跳过：连接失败: %v", err)
	}

	svc := &Service{manager: m}
	items, err := svc.ListDir("qiniu", "/")
	if err != nil {
		t.Fatalf("列桶失败: %v", err)
	}
	if len(items) == 0 {
		t.Fatal("没有返回任何桶")
	}
	t.Logf("七牛云桶数量: %d", len(items))
	for _, item := range items {
		t.Logf("  桶: %s (path=%s, is_dir=%v)", item["name"], item["path"], item["is_dir"])
	}
}

func TestQiniuBucketListDir(t *testing.T) {
	ak := getEnvOrSkip(t, "QINIU_AK")
	sk := getEnvOrSkip(t, "QINIU_SK")

	m := &Manager{}
	if err := m.Connect("qiniu", ak, sk, ""); err != nil {
		t.Skipf("跳过：连接失败: %v", err)
	}

	svc := &Service{manager: m}
	items, err := svc.ListDir("qiniu", "/")
	if err != nil || len(items) == 0 {
		t.Skipf("跳过：无法列桶")
	}

	bucketName, _ := items[0]["name"].(string)
	t.Logf("进入桶: %s", bucketName)

	path := "/" + bucketName + "/"
	files, err := svc.ListDir("qiniu", path)
	if err != nil {
		t.Fatalf("列桶内文件失败: %v", err)
	}
	t.Logf("桶内文件数量: %d", len(files))
	for _, f := range files {
		t.Logf("  %s (is_dir=%v, size=%v)", f["name"], f["is_dir"], f["size"])
	}

	client := m.GetClient("qiniu", bucketName)
	if client == nil {
		t.Error("桶级客户端未缓存")
	}
}

func TestAliyunConnect(t *testing.T) {
	ak := getEnvOrSkip(t, "ALIYUN_AK")
	sk := getEnvOrSkip(t, "ALIYUN_SK")
	ep := os.Getenv("ALIYUN_EP")
	if ep == "" {
		ep = "oss-cn-shenzhen.aliyuncs.com"
	}

	m := &Manager{}
	err := m.Connect("aliyun", ak, sk, ep)
	if err != nil {
		t.Fatalf("阿里云连接失败: %v", err)
	}
}

func TestAliyunListBuckets(t *testing.T) {
	ak := getEnvOrSkip(t, "ALIYUN_AK")
	sk := getEnvOrSkip(t, "ALIYUN_SK")
	ep := os.Getenv("ALIYUN_EP")
	if ep == "" {
		ep = "oss-cn-shenzhen.aliyuncs.com"
	}

	m := &Manager{}
	if err := m.Connect("aliyun", ak, sk, ep); err != nil {
		t.Skipf("跳过：连接失败: %v", err)
	}

	svc := &Service{manager: m}
	items, err := svc.ListDir("aliyun", "/")
	if err != nil {
		t.Fatalf("列桶失败: %v", err)
	}
	if len(items) == 0 {
		t.Fatal("没有返回任何桶")
	}
	t.Logf("阿里云桶数量: %d", len(items))
	for _, item := range items {
		t.Logf("  桶: %s (path=%s)", item["name"], item["path"])
	}
}

func TestAliyunBucketListDir(t *testing.T) {
	ak := getEnvOrSkip(t, "ALIYUN_AK")
	sk := getEnvOrSkip(t, "ALIYUN_SK")
	ep := os.Getenv("ALIYUN_EP")
	if ep == "" {
		ep = "oss-cn-shenzhen.aliyuncs.com"
	}

	m := &Manager{}
	if err := m.Connect("aliyun", ak, sk, ep); err != nil {
		t.Skipf("跳过：连接失败: %v", err)
	}

	svc := &Service{manager: m}
	items, err := svc.ListDir("aliyun", "/")
	if err != nil || len(items) == 0 {
		t.Skipf("跳过：无法列桶")
	}

	var bucketName string
	for _, item := range items {
		if item["name"] == "f-kit" {
			bucketName = "f-kit"
			break
		}
	}
	if bucketName == "" {
		bucketName, _ = items[0]["name"].(string)
	}
	t.Logf("进入桶: %s", bucketName)

	path := "/" + bucketName + "/"
	files, err := svc.ListDir("aliyun", path)
	if err != nil {
		t.Fatalf("列桶内文件失败: %v", err)
	}
	t.Logf("桶内文件数量: %d", len(files))
	for _, f := range files {
		t.Logf("  %s (is_dir=%v)", f["name"], f["is_dir"])
	}
}

func TestParseBucketPath(t *testing.T) {
	tests := []struct {
		input      string
		wantBucket string
		wantKey    string
	}{
		{"/bucket/file.txt", "bucket", "file.txt"},
		{"/bucket/dir/file.txt", "bucket", "dir/file.txt"},
		{"/bucket/", "bucket", ""},
		{"/bucket", "bucket", ""},
		{"/", "", ""},
		{"", "", ""},
	}
	for _, tt := range tests {
		bucket, key := parseBucketPath(tt.input)
		if bucket != tt.wantBucket || key != tt.wantKey {
			t.Errorf("parseBucketPath(%q) = (%q, %q), want (%q, %q)",
				tt.input, bucket, key, tt.wantBucket, tt.wantKey)
		}
	}
}

func TestDisconnect(t *testing.T) {
	ak := getEnvOrSkip(t, "QINIU_AK")
	sk := getEnvOrSkip(t, "QINIU_SK")

	m := &Manager{}
	if err := m.Connect("qiniu", ak, sk, ""); err != nil {
		t.Skipf("跳过：连接失败: %v", err)
	}

	svc := &Service{manager: m}
	items, _ := svc.ListDir("qiniu", "/")
	if len(items) > 0 {
		bucket, _ := items[0]["name"].(string)
		svc.ListDir("qiniu", "/"+bucket+"/")
	}

	m.Disconnect("qiniu")

	if _, ok := m.accounts.Load("qiniu"); ok {
		t.Error("账户凭据未被清除")
	}
}
