package user_s

import (
	"git.hilo.cn/hilo-common/domain"
	"git.hilo.cn/hilo-common/mycontext"
	"git.hilo.cn/hilo-common/resource/mysql"
	"git.hilo.cn/hilo-common/rpc"
	"gorm.io/gorm"
	"hilo-user/_const/enum/user_e"
	"hilo-user/cv/headwear_cv"
	"hilo-user/cv/medal_cv"
	"hilo-user/cv/noble_cv"
	"hilo-user/cv/property_cv"
	"hilo-user/cv/user_cv"
	"hilo-user/domain/model/country_m"
	"hilo-user/domain/model/diamond_m"
	"hilo-user/domain/model/groupPower_m"
	"hilo-user/domain/model/group_m"
	"hilo-user/domain/model/noble_m"
	"hilo-user/domain/model/user_m"
	"hilo-user/domain/model/visit_m"
	"hilo-user/domain/service/cp_s"
	"hilo-user/myerr"
)

type UserService struct {
	svc *domain.Service
}

func NewUserService(myContext *mycontext.MyContext) *UserService {
	svc := domain.CreateService(myContext)
	return &UserService{svc}
}

//用户基本信息
func (s *UserService) GetUserDetail(userId mysql.ID, myUserId mysql.ID, lang string) (*user_cv.CvUserDetail, error) {
	model := domain.CreateModelContext(s.svc.MyContext)
	model.Log.Infof("GetUserDetail %d begin", userId)
	var user user_m.User
	var err error
	if err = model.DB().First(&user, userId).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}

	//统计喜欢
	var likeN int64
	if err := model.DB().Model(&user_m.UserLike{}).Where(&user_m.UserLike{
		UserId:     myUserId,
		LikeUserId: userId,
	}).Count(&likeN).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}

	var likeMe int64
	if err := model.DB().Model(&user_m.UserLike{}).Where(&user_m.UserLike{
		UserId:     userId,
		LikeUserId: myUserId,
	}).Count(&likeMe).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}

	rel := make(map[mysql.ID]user_m.Relation, 1)
	rel[userId], _ = user_m.GetRelation(model, myUserId, userId)

	var wealthUserScore user_m.MatchWealthUserScore
	if err := model.DB().Model(&user_m.MatchWealthUserScore{}).Where(&user_m.MatchWealthUserScore{UserId: userId}).First(&wealthUserScore).Error; err != nil {
		if err != nil {
			if err == gorm.ErrRecordNotFound {
				wealthUserScore = user_m.MatchWealthUserScore{
					UserId: userId,
					Score:  0,
					Grade:  0,
				}
			} else {
				return nil, myerr.WrapErr(err)
			}
		}
	}

	var charmUserScore user_m.MatchCharmUserScore
	if err := model.DB().Model(&user_m.MatchCharmUserScore{}).Where(&user_m.MatchCharmUserScore{
		UserId: userId,
	}).First(&charmUserScore).Error; err != nil {
		if err != nil {
			if err == gorm.ErrRecordNotFound {
				charmUserScore = user_m.MatchCharmUserScore{
					UserId: userId,
					Score:  0,
					Grade:  0,
				}
			} else {
				return nil, myerr.WrapErr(err)
			}
		}
	}

	var activityUserScore user_m.MatchActityUserScore
	if err := model.DB().Model(&user_m.MatchActityUserScore{}).Where(&user_m.MatchActityUserScore{
		UserId: userId,
	}).First(&activityUserScore).Error; err != nil {
		if err != nil {
			if err == gorm.ErrRecordNotFound {
				activityUserScore = user_m.MatchActityUserScore{
					UserId: userId,
					Score:  0,
					Grade:  0,
				}
			} else {
				return nil, myerr.WrapErr(err)
			}
		}
	}
	isVip, expireTime, err := user_m.IsVip(userId)
	if err != nil {
		return nil, myerr.WrapErr(err)
	}
	svip, err := rpc.GetUserSvip(model, userId)
	if err != nil {
		return nil, myerr.WrapErr(err)
	}

	headwear, err := headwear_cv.GetCvHeadwear(userId)
	if err != nil {
		return nil, err
	}

	medals := make(map[uint64][]uint32, 0)
	medals[userId], err = user_m.GetUserMedalMerge(model.Log, mysql.Db, userId)
	if err != nil {
		return nil, err
	}

	medals, medalInfo, err := medal_cv.GetMedalInfoMap(mysql.Db, medals)
	if err != nil {
		return nil, err
	}

	rooms, err := group_m.RoomLivingUserIdFilter(model, []uint64{userId})
	if err != nil {
		return nil, err
	}
	// 2022-05-13 个人详情页:当用户在加锁的房间时,不显示进入房间的图标
	if g, ok := rooms[userId]; ok {
		gi, err := group_m.GetGroupInfo(model, g)
		if err != nil {
			return nil, err
		}
		if gi != nil && len(gi.Password) > 0 {
			rooms[userId] = ""
		}
	}
	cp, err := cp_s.NewCpService(s.svc.MyContext).GetUserCp(userId, lang)
	if err != nil {
		return nil, err
	} else if cp != nil && cp.CpUserInfo != nil && cp.CpUserInfo.Avatar != nil && headwear != nil {
		headwear.HeadwearIcon = *cp.CpUserInfo.Avatar
	}

	groupPowerId, groupPowerName, err := groupPower_m.GetUserGroupPower(model, userId)
	if err != nil {
		return nil, err
	}
	powers := map[mysql.ID]uint64{userId: groupPowerId}
	powerNames := map[mysql.ID]string{userId: groupPowerName}
	groupPower, _ := rpc.GetGroupPower(model, groupPowerId)

	up := user_m.UserProperty{}
	rides, err := up.BatchGet(mysql.Db, []uint64{userId})
	if err != nil {
		return nil, err
	}

	//rp := res_m.ResProperty{}
	//properties, err := rp.GetAll(mysql.Db)
	_, area, err := user_m.GetUserCountryArea(model, userId)
	if err != nil {
		return nil, err
	}
	properties, err := property_cv.GetPropertyAll(mysql.Db, area)
	if err != nil {
		return nil, err
	}
	ride := property_cv.CvProperty{
		Id:             rides[user.ID],
		PicUrl:         properties[rides[user.ID]].PicUrl,
		EffectUrl:      properties[rides[user.ID]].EffectUrl,
		SenderAvatar:   properties[rides[user.ID]].SenderAvatar,
		ReceiverAvatar: properties[rides[user.ID]].ReceiverAvatar,
		Using:          true,
	}
	noble, err := noble_m.FindActiveNoble(mysql.Db, userId)
	if err != nil {
		return nil, err
	}

	//判断是不是工会
	userTradeUnion, err := user_m.GetUserTradeUnion(myUserId)
	if err != nil {
		return nil, err
	}

	superManagerMap, err := user_m.GetSuperManagerMap([]uint64{userId})
	if err != nil {
		return nil, err
	}

	// 群组信息
	myGroups, err := group_m.FindGroupByOwner(model, userId)
	if err != nil {
		return nil, err
	}

	// 手机绑定信息
	// 第三方账号绑定信息
	phoneInfo := new(user_m.UserPhoneInfo)
	var thirdList []int8
	if userId == myUserId {
		thirdList = make([]int8, 0, 5)
		// 手机绑定信息
		bindInfo, err := user_m.GetUserBindInfoByUserId(model, userId)
		if err != nil && err != gorm.ErrRecordNotFound {
			return nil, err
		}
		if bindInfo != nil {
			if len(bindInfo.Phone) > 2 {
				phoneInfo.Phone = bindInfo.Phone[:2] + "****" + bindInfo.Phone[len(bindInfo.Phone)-2:]
			}
			phoneInfo.PhoneCountry = bindInfo.PhoneCountry
			phoneInfo.AreaCode = bindInfo.AreaCode
			phoneInfo.Icon = bindInfo.Icon
			thirdList = append(thirdList, 1)
		}
		// 第三方账号绑定信息
		thirdInfoList, err := user_m.GetUserOauthByUserId(model, userId, 0)
		if err != nil {
			return nil, err
		}
		if thirdInfoList != nil {
			for _, v := range thirdInfoList {
				thirdList = append(thirdList, v.ThirdPartyType)
			}
		}
	}
	// 国家管理员
	countryManager, err := country_m.GetCountryMgr(model, userId)
	if err != nil {
		return nil, err
	}
	var cvCountryManager *user_cv.CVCountryManager
	if countryManager != nil {
		cvCountryManager = &user_cv.CVCountryManager{
			Country: countryManager.Country,
			Role:    countryManager.Role,
		}
	}

	return userToDetailOne(model, &user, myUserId, userTradeUnion, likeN > 0, likeMe > 0,
		rel, isVip, expireTime, svip, headwear, ride, wealthUserScore.Grade, charmUserScore.Grade,
		activityUserScore.Grade, medals[userId], medalInfo[userId], rooms[userId], powers[userId], powerNames[userId], groupPower,
		noble, superManagerMap[userId], myGroups, phoneInfo, thirdList, cvCountryManager, cp)
}

// 单用户版,简化参数
func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID, userTradeUnion *user_m.UserTradeUnion, isLike bool, likeMe bool, hvMap map[mysql.ID]user_m.Relation,
	isVip bool, vipExpireTime *int64, svip rpc.CvSvip, headwear *headwear_cv.CvHeadwear, ride property_cv.CvProperty, wealthGrade uint32, charmGrade uint32, activityGrade uint32,
	medals []uint32, medalInfo []medal_cv.CvMedal, room string, power uint64, powerName string, groupPower rpc.CvGroupPowerInfo, noble *noble_m.UserNoble, isOfficialStaff bool,
	myGroups []group_m.GroupInfo, phoneInfo *user_m.UserPhoneInfo, thirdList []int8, countryManager *user_cv.CVCountryManager, cp *user_cv.CvCp) (*user_cv.CvUserDetail, error) {

	room, err := group_m.ToTxGroupId(model, room)
	if err != nil {
		model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err)
		room = ""
	}

	cvUserDetail := &user_cv.CvUserDetail{
		CvUserBase: user_cv.CvUserBase{
			Id:              &user.ID,
			Avatar:          StrNil(IfLogoutStr(IfLogout(user.LogoutTime), "", user.Avatar)),
			DefaultAvatar:   &user.DefaultAvatar,
			ExternalId:      StrToString(&user.ExternalId),
			Nick:            StrNil(IfLogoutStr(IfLogout(user.LogoutTime), user.Code, user.Nick)),
			Description:     StrNil(IfLogoutStr(IfLogout(user.LogoutTime), "", user.Description)),
			Sex:             TypeToUint8(&user.Sex),
			Country:         StrNil(user.Country),
			CountryIcon:     StrNil(user.CountryIcon),
			Code:            StrToString(&user.Code),
			IsPrettyCode:    user.IsPrettyCode(),
			IsVip:           isVip,
			IsOfficialStaff: isOfficialStaff,
			VipExpireTime:   vipExpireTime,
			Svip:            svip,
			Medals:          IfLogoutMedals(IfLogout(user.LogoutTime), []uint32{}, medals),
			MedalInfo:       IfLogoutMedalInfo(IfLogout(user.LogoutTime), []medal_cv.CvMedal{}, medalInfo),
			Headwear:        IfLogoutHeadwear(IfLogout(user.LogoutTime), nil, headwear),
			Ride:            IfLogoutRide(IfLogout(user.LogoutTime), property_cv.CvProperty{}, ride),
		},
		IsPush:            TypeToUint8(&user.IsPush),
		IsLike:            &isLike,
		IsLikeMe:          &likeMe,
		WealthUserGrade:   wealthGrade,
		CharmUserGrade:    charmGrade,
		ActivityUserGrade: activityGrade,
		CurrentRoom:       room,
		MyGroupPower:      power,
		MyGroupPowerName:  powerName,
		GroupPower:        groupPower,
		PhoneInfo:         phoneInfo,
		ThirdList:         thirdList,
		CountryManager:    countryManager,
		Cp:                cp,
	}
	if noble != nil {
		cvUserDetail.Noble = noble_cv.CvNoble{
			Level:   noble.Level,
			EndTime: noble.EndTime.Unix(),
		}
	}

	//本人,计算,喜欢统计,钻石数量
	if user.ID == myUserId {
		cvUserDetail.IsShowAge = TypeToUint8((*mysql.Type)(&user.IsShowAge))
		cvUserDetail.Birthday = BirthdayToUint64(&user.Birthday)

		//喜欢统计
		var userCount user_m.UserCount
		err := model.DB().Where(&user_m.UserCount{
			UserId: myUserId,
			Type:   user_e.CountTypeLikeMe,
		}).First(&userCount).Error
		if err != nil && err != gorm.ErrRecordNotFound {
			return nil, myerr.WrapErr(err)
		}
		cvUserDetail.LikeCount = NumToUint32(&userCount.Num)

		//我喜欢统计
		var userILikeCount user_m.UserCount
		err = mysql.Db.Where(&user_m.UserCount{
			UserId: myUserId,
			Type:   user_e.CountTypeLike,
		}).First(&userILikeCount).Error
		if err != nil && err != gorm.ErrRecordNotFound {
			return nil, myerr.WrapErr(err)
		}
		cvUserDetail.ILikeCount = NumToUint32(&userILikeCount.Num)

		//访问统计
		var visitCount int64
		err = mysql.Db.Model(&visit_m.UserVisit{}).Where(&visit_m.UserVisit{
			VisitUserId: myUserId,
		}).Count(&visitCount).Error
		if err != nil && err != gorm.ErrRecordNotFound {
			return nil, myerr.WrapErr(err)
		}
		vc := uint32(visitCount)
		cvUserDetail.VisitCount = NumToUint32((*mysql.Num)(&vc))

		//钻石数量
		cvDiamond, err := diamond_m.GetDiamondAccountByUserId(model, myUserId)
		if err != nil {
			return nil, err
		}
		cvUserDetail.DiamondNum = &cvDiamond.DiamondNum
		cvUserDetail.PinkDiamondNum = &cvDiamond.PinkDiamondNum

		isAgent := user_m.IsAgent(myUserId)
		cvUserDetail.IsAgentMgr = &isAgent
	} else {
		//不是本人
		if user.IsShowAge == mysql.OPEN {
			cvUserDetail.Birthday = BirthdayToUint64(&user.Birthday)
		}
	}

	if userTradeUnion == nil {
		isTradeUnionFlag := false
		cvUserDetail.IsTradeUnion = &isTradeUnionFlag
		cvUserDetail.IsTradeUnionMatchNotification = nil
	} else {
		isTradeUnionFlag := true
		cvUserDetail.IsTradeUnion = &isTradeUnionFlag
		isTradeUnionMatchNotificationFlag := userTradeUnion.MatchNotification == mysql.OPEN
		cvUserDetail.IsTradeUnionMatchNotification = &isTradeUnionMatchNotificationFlag
	}

	// 永恒之心的值
	hv, ok := hvMap[user.ID]
	if ok {
		cvUserDetail.HeartValue = hv.HeartValue
		cvUserDetail.HeartValueMax = hv.HeartValueMax
		cvUserDetail.MeetDays = hv.MeetDays
	} else {
		cvUserDetail.HeartValueMax = 0
	}

	// 拥有的群组id
	if len(myGroups) > 0 {
		cvUserDetail.GroupId = myGroups[0].TxGroupId
	}

	return cvUserDetail, nil
}