package repositories

import (
	"context"
	"encoding/json"
	"fusenapi/model/gmodel"

	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/zeromicro/go-zero/core/logc"
	"gorm.io/gorm"
)

func NewResource(gormDB *gorm.DB, bLMServiceUrl *string, awsSession *session.Session) Resource {
	return &defaultResource{
		MysqlConn:     gormDB,
		BLMServiceUrl: bLMServiceUrl,
		AwsSession:    awsSession,
	}
}

type (
	defaultResource struct {
		MysqlConn     *gorm.DB
		BLMServiceUrl *string
		AwsSession    *session.Session
	}
	Resource interface {
		// 更新metadata
		UpdateMetadata(ctx context.Context, in *UpdateMetadataReq) (*UpdateMetadataRes, error)
	}
)

// 全局
type (
	Cropping struct {
		ResourceId  string `json:"resource_id"`
		ResourceUrl string `json:"resource_url"`
		Width       int64  `json:"width"`
		Height      int64  `json:"height"`
	}
)

/* 更新metadata */
type (
	UpdateMetadataReq struct {
		ResourceId    string                 `json:"resource_id"`
		MetadataChild map[string]interface{} `json:"metadata_child"`
	}
	UpdateMetadataRes struct{}
)

// 更新metadata
func (d *defaultResource) UpdateMetadata(ctx context.Context, in *UpdateMetadataReq) (*UpdateMetadataRes, error) {
	// 事务处理
	err := d.MysqlConn.Transaction(func(tx *gorm.DB) error {
		var NewFsResourceModel = gmodel.NewFsResourceModel(tx)
		oldResourceWhere := tx.Where("resource_id = ?", in.ResourceId)
		oldResource, err := NewFsResourceModel.FindOneByQuery(ctx, oldResourceWhere, nil)
		if err != nil || oldResource.ResourceId == "" {
			logc.Errorf(ctx, "FindOneByQuery oldResource error: %v", err)
			return err
		}
		var newResourceMetadata string
		if oldResource.Metadata != nil && *oldResource.Metadata != "{}" {
			var oldResourceMetadata map[string]interface{}
			err = json.Unmarshal([]byte(*oldResource.Metadata), &oldResourceMetadata)
			if err != nil {
				logc.Errorf(ctx, "Unmarshal oldResourceMetadata error: %v", err)
				return err
			}
			for k, v := range in.MetadataChild {
				switch val := v.(type) {
				case map[string]interface{}:
					oldResourceMetadataData := oldResourceMetadata[k].(map[string]interface{})
					for key := range val {
						oldResourceMetadataData[key] = val
					}
					oldResourceMetadata[k] = oldResourceMetadataData
				}
			}
			oldResourceMetadataB, err := json.Marshal(oldResourceMetadata)
			if err != nil {
				logc.Errorf(ctx, "Marshal oldResourceMetadata error: %v", err)
				return err
			}
			newResourceMetadata = string(oldResourceMetadataB)
		} else {
			var resourceMetadata = make(map[string]interface{}, len(in.MetadataChild))
			for k, v := range in.MetadataChild {
				switch val := v.(type) {
				case map[string]interface{}:
					var resourceMetadataData = make(map[string]interface{}, len(val))
					for key := range val {
						resourceMetadataData[key] = val
					}
					resourceMetadata[k] = resourceMetadataData
				}
			}
			newResourceMetadataB, err := json.Marshal(resourceMetadata)
			if err != nil {
				logc.Errorf(ctx, "Marshal oldResourceMetadata error: %v", err)
				return err
			}
			newResourceMetadata = string(newResourceMetadataB)
		}
		oldResource.Metadata = &newResourceMetadata
		_, err = NewFsResourceModel.BuilderUpdate(ctx, tx, oldResource)
		if err != nil {
			logc.Errorf(ctx, "Transaction UpdateMetadata error: %v", err)
			return err
		}
		return nil

	})
	if err != nil {
		logc.Errorf(ctx, "BuilderUpdate oldResource error: %v", err)
		return nil, err
	}
	return nil, nil
}

/* 更新metadata */