package common

import (
	"encoding/json"
	"fmt"
	"hash/crc64"
	"sort"

	"bsm/full/module/social/relation/internal/impl"
	"bsm/full/module/social/relation/internal/models"
	pb "bsm/full/module/social/relation/pb"
)

var (
	Filed string = "relation_identity as identity,nickname,avatar,sex,province,city,area,sign"
)

// 根据identity获取会员信息卡片
func GetrelationInfoDetailCard(identity string) (card *pb.RelationItem, err error) {
	err = impl.DBService.Table("relation_extend").Select(Filed).Where("relation_identity = ?", identity).First(&card).Error
	return
}

// 根据id数组获取多条会员信息卡片
func GetrelationInfoDetailCardById(ids []uint) (cards []*pb.RelationItem, err error) {
	err = impl.DBService.Table("relation_extend").Select(Filed).Where("relation_id in ?", ids).Find(&cards).Error
	return
}

// 实现将2个字符串，不论先后顺序输入，输出得到的唯一值都是一样的。
func UniqueSessionID(s1, s2 string) string {
	strs := []string{s1, s2}
	sort.Strings(strs)
	table := crc64.MakeTable(crc64.ECMA)
	return fmt.Sprintf("%x", crc64.Checksum([]byte(strs[0]+strs[1]), table))
}

// 根据用户ID，找到用户的申请好友信息
func CollectionFriendApply(id uint) (reply *pb.ApplyFetchReply, err error) {
	var (
		version      int64
		ids          []uint
		last_msg_ids []uint
		maxSize      int = 50
		applys           = make([]*models.FriendApply, 0)
		replyItems       = make([]*pb.ApplyItem, 0)
		mapCards         = make(map[string]*pb.RelationItem)

		messages    = make([]*models.FriendApplyMessage, 0)
		mapMessages = make(map[uint]*pb.MessageItem)
	)
	reply = &pb.ApplyFetchReply{}

	err = impl.DBService.Where("to_id=? ", id).Order("id desc").Limit(maxSize).Find(&applys).Error
	if err != nil {
		return nil, err
	}

	for _, item := range applys {
		ids = append(ids, item.FromID)
		last_msg_ids = append(last_msg_ids, item.LastMessageID)
	}

	result, err := GetrelationInfoDetailCardById(ids)
	if err != nil {
		return nil, err
	}
	for _, item := range result {
		mapCards[item.Identity] = item
	}

	err = impl.DBService.Where("id in ?", last_msg_ids).Find(&messages).Error
	if err != nil {
		return nil, err
	}
	for _, item := range messages {
		mapMessages[item.ID] = &pb.MessageItem{
			RelationIdentity: item.PassportIdentity,
			Body:             item.Body,
			CreatedAt:        item.CreatedAt.Local().Format("2006-01-02 15:04:05"),
		}
	}

	for _, item := range applys {
		var applyItem = &pb.ApplyItem{}
		applyItem.Identity = item.Identity
		applyItem.CreatedAt = item.CreatedAt.Local().Format("2006-01-02 15:04:05")
		applyItem.Status = int32(item.Status)

		if _, ok := mapCards[item.FromIdentity]; ok {
			applyItem.From = mapCards[item.FromIdentity]
		}

		if _, ok := mapMessages[item.LastMessageID]; ok {
			applyItem.Message = mapMessages[item.LastMessageID]
		}

		replyItems = append(replyItems, applyItem)
		version = int64(item.ID)
	}

	reply.Applys = replyItems
	reply.Version = version
	return
}

// 根据用户ID，找到用户的好友信息和分组信息
func CollectionFriendData(id uint) (reply *pb.FriendsReply, err error) {
	var (
		version int64
		ids     []uint

		relationFriend   = make([]models.RelationFriend, 0)
		mapRelationFrend = make(map[uint]models.RelationFriend)

		friendInTag    = make([]models.FriendInTag, 0)
		mapFriendInTag = make(map[string][]string)
	)
	reply = &pb.FriendsReply{}
	impl.DBService.Where("relation_id=?", id).Order("id desc").Find(&relationFriend)

	for _, item := range relationFriend {
		ids = append(ids, item.ID)
		mapRelationFrend[item.ID] = item
		version = int64(item.ID)
	}

	impl.DBService.Where("relation_id=?", id).Find(&friendInTag)

	for _, item := range friendInTag {
		mapFriendInTag[item.FriendIdentity] = append(mapFriendInTag[item.FriendIdentity], item.TagIdentity)
	}

	err = impl.DBService.Model(models.FriendTag{}).Where("relation_id=?", id).Order("id asc").Scan(&reply.Tags).Error
	if err != nil {
		return
	}

	reply.Friends, err = GetrelationInfoDetailCardById(ids)
	for idx, item := range reply.Friends {
		reply.Friends[idx].RemarkName = item.RemarkName
		reply.Friends[idx].Popular = item.Popular
		if _, ok := mapFriendInTag[item.Identity]; ok {
			reply.Friends[idx].Tags = mapFriendInTag[item.Identity]
		}
	}

	reply.Version = version

	return
}

// 根据Match表获取多条会员信息卡片
func GetrelationInfoDetailCardByMatch(relation_identity string, offset, limit int) (cards []*pb.RelationItem, err error) {
	sql := `Select 
			pe.relation_identity as identity, 
			pe.name,
			pe.avatar,
			pe.birthday,
			pe.sex,
			pe.province,
			pe.city,
			pe.area,
			pe.sign,
			rm.status as foreign_status 
			From relation_match as rm,relation_extend as pe 
			Left join pe on pe.relation_identity=rm.recommend_identity
			Where rm.relation_identity=?
			Offset ?
			Limit ?
			Order by rm.id Desc`
	err = impl.DBService.Raw(sql, relation_identity, offset, limit).Scan(&cards).Error
	return
}

func SetCache(identity string, collectionName string, in interface{}) error {
	key := "/RF/" + identity + "/" + collectionName
	val, err := json.Marshal(in)
	if err != nil {
		return err
	}
	err = impl.RedisService.Client.Set(impl.RedisService.Ctx, key, string(val), 0).Err()
	if err != nil {
		return err
	}

	return nil
}

func GetCache(identity, collectionName string) (reply *pb.ApplyFetchReply, err error) {
	key := "/RF/" + identity + "/" + collectionName
	collection, err := impl.RedisService.Client.Get(impl.RedisService.Ctx, key).Result()
	if err != nil {
		return
	}
	err = json.Unmarshal([]byte(collection), &reply)
	if err != nil {
		return
	}

	return
}
