package game

import (
	"server/db"
	"server/game/mod/msg"
	GoUtil "server/game_util"
	"server/pkg/github.com/name5566/leaf/log"
	"sort"
)

func (p *Player) GetVisitorPlayer() int {
	PlayroomMod := p.PlayMod.getPlayroomMod()
	VisitorList := PlayroomMod.GetVisitor()                 // 到访用户
	TodayVisitedUsers := PlayroomMod.GetTodayVisitedUsers() // 今日已互动用户
	FriendMod := p.PlayMod.getFriendMod()
	type sortData struct {
		Uid  int
		Time int64
	}
	PlayerList := make([]sortData, 0)
	PlayerList2 := make([]sortData, 0)
	Now := GoUtil.Now()
	/**
		排除当日玩家已对其发起过交互的用户
	优先选择24小时内曾经与玩家进行过宠物交互的好友
	若存在复数对象的情况下，优先选择交互发生时间与当前时间最近的好友
	若不存在符合条件的用户，则选择24小时内曾经与玩家进行过宠物交互的陌生用户
	若存在复数对象的情况下，优先选择交互发生时间与当前时间最近的用户
	若不存在符合条件的用户，则选择24小时内登入过游戏且上次登入时间与当前时间最近的好友
	若不存在符合条件的用户，则依据以上用户推荐算法，选择一位随机推荐用户，并且在下次触发式订单完成时，不再排除已发起过交互的用户
	*/
	for k, v := range VisitorList {
		if GoUtil.InArray(k, TodayVisitedUsers) {
			continue
		}
		if v.Time < Now-86400 {
			continue
		}
		if FriendMod.CheckFriend(k) {
			PlayerList = append(PlayerList, sortData{k, v.Time})
		} else {
			PlayerList2 = append(PlayerList2, sortData{k, v.Time})
		}
	}
	if len(PlayerList) != 0 {
		sort.Slice(PlayerList, func(i, j int) bool {
			return PlayerList[i].Time > PlayerList[j].Time
		})
		return PlayerList[0].Uid
	}
	if len(PlayerList2) != 0 {
		sort.Slice(PlayerList2, func(i, j int) bool {
			return PlayerList2[i].Time > PlayerList2[j].Time
		})
		return PlayerList2[0].Uid
	}
	// 若不存在符合条件的用户，则选择24小时内登入过游戏且上次登入时间与当前时间最近的好友
	var recentFriendUid int
	var recentLoginTime int64
	for uid := range FriendMod.GetFriendList() {
		if uid == int(p.M_DwUin) {
			continue
		}
		if GoUtil.InArray(uid, TodayVisitedUsers) {
			continue
		}
		ps := G_GameLogicPtr.GetSimplePlayerByUid(uid)
		if ps == nil {
			continue
		}
		if Now-ps.Loginout > 86400 { // 24小时内登录过
			continue
		}
		if ps.Loginout > recentLoginTime {
			recentLoginTime = ps.Loginout
			recentFriendUid = uid
		}
	}
	if recentFriendUid != 0 {
		return recentFriendUid
	}
	uids, err := db.GetCommendPlayerFromDb(p.M_DwUin, GoUtil.Now()-86400, 15)
	if err != nil {
		return 0
	}
	var PlayerList4 []int
	for _, Uid := range uids {
		if Uid == int(p.M_DwUin) {
			continue
		}
		if G_GameLogicPtr.GetSimplePlayerByUid(Uid) == nil {
			continue
		}
		PlayerList4 = append(PlayerList4, Uid)
	}
	L := GoUtil.RandSliceNum(PlayerList4, 1)
	if len(L) == 0 {
		return 0
	}
	return L[0]
}

func GetRecommendPlayer(p *Player, Num int) []int {
	uids, err := db.GetCommendPlayerFromDb(p.M_DwUin, GoUtil.Now()-259200, 4)
	if err != nil {
		log.Debug("GetCommendPlayerFromDb err:%v, uid=%d", err, p.M_DwUin)
		return nil
	}
	PlayerList1 := make([]int, 0, len(uids))
	FriendMod := p.PlayMod.getFriendMod()
	for _, Uid := range uids {
		if Uid == int(p.M_DwUin) {
			continue
		}
		if FriendMod.CheckSendApply(Uid) {
			continue
		}
		if FriendMod.CheckAddBefore(Uid) {
			continue
		}
		PlayerList1 = append(PlayerList1, Uid)
	}
	// 按照时间门槛筛选用户
	filterByTime := func(excludeSeconds int64) []int {
		now := GoUtil.Now()
		result := make([]int, 0, len(PlayerList1))
		for _, Uid := range PlayerList1 {
			recommendTime := FriendMod.GetRecommendTime(Uid)
			if recommendTime == 0 || recommendTime <= now-excludeSeconds {
				result = append(result, Uid)
			}
		}
		return result
	}
	// 排查7日内推荐过的用户
	candidateList := filterByTime(604800)
	// 用户数低于5则放宽到3日
	if len(candidateList) < 5 {
		candidateList = filterByTime(259200)
	}
	// 用户数低于5则放宽到2日
	if len(candidateList) < 5 {
		candidateList = filterByTime(172800)
	}

	if len(candidateList) == 0 {
		candidateList = append(candidateList, PlayerList1...)
	}

	if len(candidateList) == 0 {
		candidateList = make([]int, 0, len(uids))
		for _, Uid := range uids {
			if Uid == int(p.M_DwUin) {
				continue
			}
			candidateList = append(candidateList, Uid)
		}
	}
	baseList := make([]*PlayerSimpleData, 0, len(candidateList))
	for _, uid := range candidateList {
		ps := G_GameLogicPtr.GetSimplePlayerByUid(uid)
		if ps != nil {
			baseList = append(baseList, ps)
		}
	}
	if len(baseList) == 0 {
		return nil
	}
	BaseMod := p.PlayMod.getBaseMod()
	level := BaseMod.GetLevel()
	diffLimit := 10
	filtered := make([]int, 0, len(baseList))
	breakNum := 100
	for breakNum > 0 {
		breakNum--
		filtered = filtered[:0]
		for _, ps := range baseList {
			if ps == nil {
				continue
			}
			diff := level - ps.Level
			if diff < 0 {
				diff = -diff
			}
			if diff <= diffLimit {
				filtered = append(filtered, ps.Uid)
			}
		}
		if len(filtered) >= 5 {
			break
		}
		diffLimit++
	}
	candidateList = filtered
	recommendList := GoUtil.RandSliceNum(candidateList, Num)
	for _, Uid := range recommendList {
		FriendMod.AddRecommend(Uid)
	}
	return recommendList
}

func GetUidByFaceBook(Fb string) (int, error) {
	sqlStr := "SELECT dwUin FROM t_player_baseinfo WHERE FaceBookId = ?"
	type Result struct {
		Uid int `db:"dwUin"`
	}
	R := Result{}
	err := db.SqlDb.Get(&R, sqlStr, Fb)
	log.Debug("Fb :%s;Uid :%d", Fb, R.Uid)
	return R.Uid, err
}

func NotifyAllFriend(p *Player, m1 *msg.Msg) {
	m := m1.Clone()
	FriendMod := p.PlayMod.getFriendMod()
	for k := range FriendMod.GetFriendList() {
		if k == int(p.M_DwUin) {
			continue
		}
		m.To = k
		FriendMgrSend(m)
	}
}
