package logic

import (
	"fusenapi/utils/auth"
	"fusenapi/utils/basic"
	"fusenapi/utils/file"
	"fusenapi/utils/s3url_to_s3id"
	"regexp"
	"strings"

	"context"

	"fusenapi/server/resource/internal/svc"
	"fusenapi/server/resource/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type ResourceBackupLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewResourceBackupLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ResourceBackupLogic {
	return &ResourceBackupLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// 处理进入前逻辑w,r
// func (l *ResourceBackupLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
// }

func (l *ResourceBackupLogic) ResourceBackup(req *types.ResourceBackupReq, userinfo *auth.UserInfo) (resp *basic.Response) {
	// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
	// userinfo 传入值时, 一定不为null
	var urls = make(map[string]string, 1000)
	switch req.TableName {
	case "fs_product_template_v2":
		// 查询所有数据
		resList, err := l.svcCtx.AllModels.FsProductTemplateV2.FindAll(l.ctx)
		if err != nil {
			l.Logger.Errorf("查询所有数据失败, err: %v", err)
			return resp.SetStatus(basic.CodeApiErr)
		}

		for _, data := range resList {
			if data.MaterialImg != nil {
				urls[s3url_to_s3id.GetS3ResourceIdFormUrl(*data.MaterialImg)] = *data.MaterialImg
			}
			if data.TemplateInfo != nil && *data.TemplateInfo != "" {
				regexStr(*data.TemplateInfo, &urls)
			}
		}
	case "fs_product":
		// 查询所有数据
		resList, err := l.svcCtx.AllModels.FsProduct.FindAll(l.ctx)
		if err != nil {
			l.Logger.Errorf("查询所有数据失败, err: %v", err)
			return resp.SetStatus(basic.CodeApiErr)
		}

		for _, data := range resList {
			if data.Cover != nil && *data.Cover != "" {
				urls[s3url_to_s3id.GetS3ResourceIdFormUrl(*data.Cover)] = *data.Cover
			}
			if data.CoverImg != nil && *data.CoverImg != "" {
				urls[s3url_to_s3id.GetS3ResourceIdFormUrl(*data.CoverImg)] = *data.CoverImg
			}
		}
	case "fs_product_template_tags":
		// 查询所有数据
		resList, err := l.svcCtx.AllModels.FsProductTemplateTags.FindAll(l.ctx)
		if err != nil {
			l.Logger.Errorf("查询所有数据失败, err: %v", err)
			return resp.SetStatus(basic.CodeApiErr)
		}

		for _, data := range resList {
			if data.Cover != nil && *data.Cover != "" {
				urls[s3url_to_s3id.GetS3ResourceIdFormUrl(*data.Cover)] = *data.Cover
			}
		}
	case "fs_product_model3d":
		// 查询所有数据
		resList, err := l.svcCtx.AllModels.FsProductModel3d.FindAll(l.ctx)
		if err != nil {
			l.Logger.Errorf("查询所有数据失败, err: %v", err)
			return resp.SetStatus(basic.CodeApiErr)
		}

		for _, data := range resList {
			if data.ModelInfo != nil && *data.ModelInfo != "" {
				regexStr(*data.ModelInfo, &urls)
			}
		}
	case "fs_product_model3d_light":
		// 查询所有数据
		resList, err := l.svcCtx.AllModels.FsProductModel3dLight.FindAll(l.ctx)
		if err != nil {
			l.Logger.Errorf("查询所有数据失败, err: %v", err)
			return resp.SetStatus(basic.CodeApiErr)
		}

		for _, data := range resList {
			if data.Info != nil && *data.Info != "" {
				regexStr(*data.Info, &urls)
			}
		}
	case "fs_tool_logs":
		// 查询所有数据
		resList, err := l.svcCtx.AllModels.FsToolLogs.FindAll(l.ctx)
		if err != nil {
			l.Logger.Errorf("查询所有数据失败, err: %v", err)
			return resp.SetStatus(basic.CodeApiErr)
		}

		for _, data := range resList {
			if data.Cover != nil && *data.Cover != "" {
				urls[s3url_to_s3id.GetS3ResourceIdFormUrl(*data.Cover)] = *data.Cover
			}
			if data.Img != nil && *data.Img != "" {
				urls[s3url_to_s3id.GetS3ResourceIdFormUrl(*data.Img)] = *data.Img
			}
		}
	}
	// 上传文件
	var upload = file.Upload{
		Ctx:        l.ctx,
		MysqlConn:  l.svcCtx.MysqlConn,
		AwsSession: l.svcCtx.AwsSession,
	}
	upload.UploadType = "oss"
	upload.AliyunOSS.AccessKeyId = l.svcCtx.Config.AliyunOSS.AccessKeyId
	upload.AliyunOSS.AccessKeySecret = l.svcCtx.Config.AliyunOSS.AccessKeySecret
	upload.AliyunOSS.Endpoint = l.svcCtx.Config.AliyunOSS.Endpoint
	upload.AliyunOSS.BasePath = l.svcCtx.Config.AliyunOSS.BasePath
	for k, v := range urls {
		err := upload.UploadFileByUrl(k, v, 1)
		if err != nil {
			l.Logger.Errorf("更新文件镜像备份失败, err: %v, key: %v, val:%v", err, k, v)
		}
	}
	return resp.SetStatus(basic.CodeOK)
}

func regexStr(unquotedStr string, urls *map[string]string) error {
	// 创建一个正则表达式
	regex := regexp.MustCompile(`"https:\\/\\/s3\.(.*?)"`)
	// 查找符合正则表达式的字符串
	matches := regex.FindAllString(unquotedStr, -1)
	var urlsData = *urls
	// 打印匹配到的字符串
	for _, match := range matches {
		var matchStr = match
		// 将字符串去转义
		matchStr = strings.Replace(matchStr, "\"", "", -1)
		matchStr = strings.Replace(matchStr, "\\", "", -1)
		urlsData[s3url_to_s3id.GetS3ResourceIdFormUrl(matchStr)] = matchStr
	}

	regex02 := regexp.MustCompile(`"https:\\/\\/fusenstorage\.s3\.(.*?)"`)
	// 查找符合正则表达式的字符串
	matches02 := regex02.FindAllString(unquotedStr, -1)
	// 打印匹配到的字符串
	for _, match := range matches02 {
		var matchStr = match
		// 将字符串去转义
		matchStr = strings.Replace(matchStr, "\"", "", -1)
		matchStr = strings.Replace(matchStr, "\\", "", -1)
		urlsData[s3url_to_s3id.GetS3ResourceIdFormUrl(matchStr)] = matchStr
	}
	return nil
}

// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
// func (l *ResourceBackupLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
// // httpx.OkJsonCtx(r.Context(), w, resp)
// }