package logic

import (
	"encoding/json"
	"errors"
	"fusenapi/model/gmodel"
	"fusenapi/utils/auth"
	"fusenapi/utils/basic"

	"context"

	"fusenapi/server/home-user-auth/internal/svc"
	"fusenapi/server/home-user-auth/internal/types"

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

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

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

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

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

func (l *UserLogoListLogic) UserLogoList(req *types.UserLogoListReq, userinfo *auth.UserInfo) (resp *basic.Response) {
	// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
	// userinfo 传入值时, 一定不为null
	// 定义用户ID
	var userId int64
	var guestId int64

	if userinfo.IsOnlooker() {
		// 如果是,返回未授权的错误码
		return resp.SetStatus(basic.CodeUnAuth)
	}

	// 用户信息
	NewFsUserInfoModel := gmodel.NewFsUserInfoModel(l.svcCtx.MysqlConn)
	userInfoGorm := NewFsUserInfoModel.BuilderDB(l.ctx, nil).Where("module = ?", "profile")
	userInfo := gmodel.FsUserInfo{}

	// 检查用户是否是游客
	if userinfo.IsGuest() {
		// 如果是,使用游客ID和游客键名格式
		guestId = userinfo.GuestId
		userInfoGorm.Where("guest_id = ?", guestId)
	} else {
		// 否则,使用用户ID和用户键名格式
		userId = userinfo.UserId
		userInfoGorm.Where("user_id = ?", userId)
	}
	var merchantCategoryIds []int64
	var logoSelectedIdd int64
	var userMaterialInfo *gmodel.RelaFsUserMaterial
	userMaterialModel := gmodel.NewFsUserMaterialModel(l.svcCtx.MysqlConn)
	resFirst := userInfoGorm.First(&userInfo)
	err := resFirst.Error
	if err != nil {
		if err != gorm.ErrRecordNotFound {
			logc.Errorf(l.ctx, "FsUserInfo First err:%+v", err)
			return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "data not found")
		}
	}
	if userInfo.Id != 0 && userInfo.Metadata != nil {
		var metadata map[string]interface{}
		err = json.Unmarshal([]byte(*userInfo.Metadata), &metadata)
		if err != nil {
			logc.Errorf(l.ctx, "userInfo.Metadata Unmarshal err:%+v", err)
			return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get data list")
		}
		logoSelectedId, isEx := metadata["logo_selected_id"]
		if isEx {
			logoSelectedIdd = int64(logoSelectedId.(float64))
			userMaterialRSB1 := userMaterialModel.RowSelectBuilder(nil).Preload("ResourceInfo", func(dbPreload *gorm.DB) *gorm.DB {
				return dbPreload.Table(gmodel.NewFsResourceModel(l.svcCtx.MysqlConn).TableName())
			}).Where("module = ?", "logo").Where("id = ?", logoSelectedIdd)
			userMaterialInfo, err = userMaterialModel.FindOneData(l.ctx, userMaterialRSB1)
			if err != nil {
				if err != gorm.ErrRecordNotFound {
					logc.Errorf(l.ctx, "FsUserInfo First err:%+v", err)
					return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get data list")
				}
			}
			var metadataMapuserMaterialInfo map[string]interface{}
			if userMaterialInfo.Metadata != nil {
				json.Unmarshal(*userMaterialInfo.Metadata, &metadataMapuserMaterialInfo)
				merchantCategoryuserMaterialInfo, merchantCategoryEixuserMaterialInfo := metadataMapuserMaterialInfo["merchant_category"]
				if merchantCategoryEixuserMaterialInfo {
					merchantCategoryIduserMaterialInfo := int64(merchantCategoryuserMaterialInfo.(float64))
					merchantCategoryIds = append(merchantCategoryIds, merchantCategoryIduserMaterialInfo)
				}
			}
			userMaterialInfo.MetaDataMap = metadataMapuserMaterialInfo
		}
	}

	// 历史列表

	userMaterialRSB := userMaterialModel.RowSelectBuilder(nil).Preload("ResourceInfo", func(dbPreload *gorm.DB) *gorm.DB {
		return dbPreload.Table(gmodel.NewFsResourceModel(l.svcCtx.MysqlConn).TableName())
	}).Where("module = ?", "logo").Order("id desc").Limit(5)
	if userId != 0 {
		userMaterialRSB.Where("user_id = ?", userId)
	} else {
		userMaterialRSB.Where("guest_id = ?", guestId)
	}
	list, err := userMaterialModel.FindList(l.ctx, userMaterialRSB, nil, "")
	if err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			logx.Error(err)
			return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get data list")
		}
	}
	var isDefaul bool = false
	if len(list) > 0 {
		for _, v := range list {
			var metadataMap map[string]interface{}
			if v.Metadata != nil {
				json.Unmarshal(*v.Metadata, &metadataMap)

				merchantCategory, merchantCategoryEix := metadataMap["merchant_category"]
				if merchantCategoryEix {
					merchantCategoryId := int64(merchantCategory.(float64))
					merchantCategoryIds = append(merchantCategoryIds, merchantCategoryId)
				}
				metadataMap["merchant_category_info"] = nil
				v.MetaDataMap = metadataMap
			}

			if v.ResourceInfo != nil {
				if v.ResourceInfo.Metadata != nil {
					var resourceMetadata map[string]interface{}
					json.Unmarshal([]byte(*v.ResourceInfo.Metadata), &resourceMetadata)
					v.ResourceInfo.MetaDataMap = resourceMetadata
				}
			}

			if logoSelectedIdd == v.Id {
				isDefaul = true
			}
		}
		if len(merchantCategoryIds) > 0 {
			newFsMerchantCategoryModel := gmodel.NewFsMerchantCategoryModel(l.svcCtx.MysqlConn)
			fsMerchantCategoryDb := newFsMerchantCategoryModel.BuilderDB(l.ctx, nil).Model(&gmodel.FsMerchantCategory{}).Where("id in ?", merchantCategoryIds)
			resfsMerchantCategoryDb, err := newFsMerchantCategoryModel.FindAll(fsMerchantCategoryDb, nil, "")
			if err != nil {
				logx.Error(err)
				return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "newFsMerchantCategoryModel FindAll db")
			}
			merchantCategoryDataLen := len(resfsMerchantCategoryDb)
			var merchantCategoryData = make(map[int64]*gmodel.FsMerchantCategory, merchantCategoryDataLen)
			if merchantCategoryDataLen > 0 {
				for _, v := range resfsMerchantCategoryDb {
					merchantCategoryData[v.Id] = v
				}
			}
			for k, v := range list {
				if !isDefaul && k == 4 && userMaterialInfo != nil {
					v = userMaterialInfo
				}
				if v.MetaDataMap != nil {
					merchantCategory1, merchantCategoryEix1 := v.MetaDataMap["merchant_category"]
					if merchantCategoryEix1 {
						merchantCategoryId1 := int64(merchantCategory1.(float64))
						v.MetaDataMap["merchant_category_info"] = merchantCategoryData[merchantCategoryId1]
					} else {
						v.MetaDataMap["merchant_category_info"] = nil
					}
				}
				list[k] = v
			}
		}
	}
	return resp.SetStatus(basic.CodeOK, map[string]interface{}{
		"list": list,
	})
}