package oss_core

import (
	"context"
	"fmt"
	"reflect"
	"sundynix-micro-go/app/file/rpc/file"
	"sundynix-micro-go/app/file/rpc/fileservice"
	"sync"
)

type CachedUploader struct {
	Uploader Uploader
	Config   *file.StorageConfigInfo
}

var (
	uploaderCache sync.Map // map[string]*CachedUploader
	cacheMutex    sync.Mutex
)

// OSSFactory 工厂结构体
type OSSFactory struct {
	fileRpc fileservice.FileService
}

func NewOSSFactory(fileRpc fileservice.FileService) *OSSFactory {
	return &OSSFactory{
		fileRpc: fileRpc,
	}
}

// GetActiveUploader 获取当前激活的存储上传实例
func (f *OSSFactory) GetActiveUploader(ctx context.Context) (Uploader, error) {
	resp, err := f.fileRpc.GetDefaultStorageConfig(ctx, &fileservice.GetDefaultStorageConfigReq{})
	if err != nil || resp.Config == nil {
		return nil, fmt.Errorf("未找到激活的存储配置: %v", err)
	}

	conf := resp.Config

	// 1. 尝试从缓存获取
	if cachedVal, ok := uploaderCache.Load(conf.Id); ok {
		cachedItem := cachedVal.(*CachedUploader)
		// 优雅之处：深度对比配置是否发生变化，完美支持前端动态修改配置后实时热加载
		if reflect.DeepEqual(cachedItem.Config, conf) {
			return cachedItem.Uploader, nil
		}
	}

	// 2. 加锁防止高并发下的重复实例化
	cacheMutex.Lock()
	defer cacheMutex.Unlock()

	// 3. Double-Check
	if cachedVal, ok := uploaderCache.Load(conf.Id); ok {
		cachedItem := cachedVal.(*CachedUploader)
		if reflect.DeepEqual(cachedItem.Config, conf) {
			return cachedItem.Uploader, nil
		}
	}

	// 4. 实例化新的 Uploader
	var uploader Uploader
	switch conf.Type {
	case "minio":
		uploader, err = NewMinioUploader(conf)
	case "aliyun":
		uploader, err = NewAliyunUploader(conf)
	case "tencent":
		uploader, err = NewTencentUploader(conf)
	case "qiniu":
		uploader, err = NewQiniuUploader(conf)
	default:
		return nil, fmt.Errorf("不支持的存储类型: %s", conf.Type)
	}

	if err != nil {
		return nil, err
	}

	// 5. 更新缓存
	uploaderCache.Store(conf.Id, &CachedUploader{
		Uploader: uploader,
		Config:   conf,
	})

	return uploader, nil
}
