package group_s

import (
	"encoding/json"
	"git.hilo.cn/hilo-common/domain"
	"git.hilo.cn/hilo-common/mycontext"
	"git.hilo.cn/hilo-common/resource/config"
	"git.hilo.cn/hilo-common/resource/mysql"
	"gorm.io/gorm"
	"hilo-group/_const/enum/group_e"
	"hilo-group/_const/enum/mgr_e"
	"hilo-group/_const/redis_key"
	"hilo-group/domain/event/group_ev"
	"hilo-group/domain/model/group_m"
	"hilo-group/domain/model/mgr_m"
	"hilo-group/domain/model/noble_m"
	"hilo-group/domain/model/res_m"
	"hilo-group/domain/model/user_m"
	"hilo-group/domain/service/signal_s"
	"hilo-group/myerr"
	"strconv"
	"time"
)

type GroupService struct {
	svc *domain.Service
}

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

// 取本周最高的扶持等级 fixme:删除这个过渡函数
func (s *GroupService) GetWeekMaxSupportLevelMap() (map[string]uint8, error) {
	return s.GetSupportLevelMap(time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
}

func (s *GroupService) GetSupportLevelMap(now time.Time) (map[string]uint8, error) {
	model := domain.CreateModel(s.svc.CtxAndDb)

	_, _, period := group_m.GetSupportLevelTime(now)

	levels, err := GetAllSupportLevel(model, period)
	if err != nil {
		return nil, err
	}
	model.Log.Debugf("GetSupportLevelMap, GET %s: %v", period, levels)

	result := make(map[string]uint8, 0)
	if len(levels) > 0 {
		for g, l := range levels {
			le, err := strconv.ParseUint(l, 10, 8)
			if err == nil {
				result[g] = uint8(le)
			}
		}
	} else {
		result, err = group_m.GetAllGroupSupportResult(model.Db, period)
		if err == nil {
			ret, err := SaveAllSupportLevel(model, period, result)
			model.Log.Infof("GetSupportLevelMap SAVE ret = %d, err: %v", ret, err)
		}
	}
	return result, nil
}

func SaveAllSupportLevel(model *domain.Model, date string, levels map[string]uint8) (int64, error) {
	values := make(map[string]interface{}, 0)
	for g, l := range levels {
		if l > 0 {
			values[g] = l
		}
	}
	if len(values) <= 0 {
		return 0, nil
	}
	key := redis_key.GetPrefixSupportLevel(date)
	ret, err := model.Redis.HSet(model, key, values).Result()

	if err == nil {
		// 设置一个TTL保险一些 TODO: 可以优化,保证数据总是有的
		ttl := time.Hour
		if !config.AppIsRelease() {
			ttl = time.Minute
		}
		model.Redis.Expire(model, key, ttl)
	}
	return ret, err
}

func GetAllSupportLevel(model *domain.Model, date string) (map[string]string, error) {
	key := redis_key.GetPrefixSupportLevel(date)
	return model.Redis.HGetAll(model, key).Result()
}

func (s *GroupService) GetJoinGroupLimit(userId mysql.ID) (uint, error) {
	model := domain.CreateModelContext(s.svc.MyContext)

	// 获取群用户上限
	maxJoin := group_e.GROUP_DEFAULT_JOIN_LIMIT
	isVip, _, err := user_m.IsVip(userId)
	if err != nil {
		return 0, err
	}
	if isVip {
		maxJoin = group_e.GROUP_VIP_JOIN_LIMIT
	}
	isNoble4, err := noble_m.CheckNobleLevel(model.Db, userId, 4)
	if err != nil {
		return 0, err
	}
	if isNoble4 {
		maxJoin = group_e.GROUP_NOBLE4_JOIN_LIMIT
	}

	guLimit := group_m.GroupUserLimits{UserId: userId}
	if err = guLimit.Get(model); err != nil && err != gorm.ErrRecordNotFound {
		return 0, err
	}
	if err != gorm.ErrRecordNotFound {
		maxJoin = guLimit.MaxJoin
	}
	return maxJoin, nil
}

//更新用户在群上的消息状态
func (s *GroupService) GroupUserMsgStatus(userId uint64, groupUuid string, msgStatus group_e.MsgStatusGroupUser) error {
	return s.svc.Transactional(func() error {
		model := domain.CreateModel(s.svc.CtxAndDb)
		//var groupInfo group_m.GroupInfo
		//if err := model.Db.Where(&group_m.GroupInfo{
		//	ImGroupId: groupUuid,
		//}).First(&groupInfo).Error; err != nil {
		//	return nil, nil, myerr.WrapErr(err)
		//}
		//
		groupUser, err := group_m.GetGroupUserOrInit(model, groupUuid, userId)
		if err != nil {
			return err
		}
		if msgStatus == group_e.NormalMsgStatusGroupUser {
			groupUser.MsgStatusNormal()
		} else if msgStatus == group_e.MuteMsgStatusGroupUser {
			groupUser.MsgStatusMute()
		} else if msgStatus == group_e.DoNotDisturbMsgStatusGroupUser {
			groupUser.MsgStatusDoNotDisturb()
		}
		return groupUser.Persistent()
	})
}

//举报群组
func (s *GroupService) ReportGroup(fromUserId mysql.ID, groupId mysql.Str, reasonType mgr_e.ReportReasonType, imageUrl mysql.Str, reason mysql.Str) error {
	return s.svc.Transactional(func() error {
		model := domain.CreateModelContext(s.svc.MyContext)
		reportGroup := mgr_m.ReportGroupAdd(model, fromUserId, groupId, reasonType, imageUrl, reason)
		err := reportGroup.Persistent()
		if err != nil {
			return err
		}
		return nil
	})
}

//群组自定义主题修改
func (s *GroupService) GroupCustomThemeUsing(userId mysql.ID, externalId string, imGroupId string, groupCustomThemeId uint64) error {
	err1 := s.svc.Transactional(func() error {
		model := domain.CreateModel(s.svc.CtxAndDb)
		groupCustomTheme, err := group_m.GetGroupCustomThemeById(model, imGroupId, groupCustomThemeId)
		if err != nil {
			return err
		}
		groupCustomTheme, err = groupCustomTheme.SetUsing(userId)
		if err != nil {
			return err
		}
		if err := groupCustomTheme.Persistent(); err != nil {
			return err
		}

		//修改数据,然后数据持久化,
		g := group_m.GroupInfo{
			ThemeId: 0,
		}
		fields := []string{"theme_id"}
		db := g.Update(model, imGroupId, fields)
		if db.Error != nil {
			return myerr.WrapErr(db.Error)
		}
		if err := groupCustomTheme.Persistent(); err != nil {
			return err
		} else {
			return nil
		}
	})
	if err1 == nil {
		type signalMsg struct {
			Name         string `json:"name"`
			Introduction string `json:"introduction"`
			Notification string `json:"notification"`
			FaceUrl      string `json:"faceUrl"`
			MicOn        bool   `json:"micOn"`
			MicNumType   group_e.GroupMicNumType
			ThemeId      uint64 `json:"themeId"`
			ThemeUrl     string `json:"themeUrl"`
			//1: 官方 2:自定义
			ThemeType uint8 `json:"themeType"`
		}
		model := domain.CreateModelContext(s.svc.MyContext)
		groupInfo, err := group_m.GetGroupInfo(model, imGroupId)
		if err != nil {
			model.Log.Error(err)
			return nil
		}
		signal := signalMsg{
			Name:         groupInfo.Name,
			Introduction: groupInfo.Introduction,
			Notification: groupInfo.Notification,
			FaceUrl:      groupInfo.FaceUrl,
			MicOn:        groupInfo.MicOn,
			MicNumType:   groupInfo.MicNumType,
			ThemeId:      0,
			ThemeUrl:     "",
			ThemeType:    0,
		}
		if groupInfo.ThemeId != 0 {
			//signal.ThemeId = groupInfo.ThemeId
			signal.ThemeType = 1
			if rows, err := res_m.GroupThemeGetAllInUse(model.Db); err == nil {
				for _, i := range rows {
					if i.ID == uint64(groupInfo.ThemeId) {
						signal.ThemeId = i.ID
						signal.ThemeUrl = i.Url
						break
					}
				}
			}
		} else {
			//可能是自定义主题
			id, url, err := group_m.GetShowCustomTheme(model, imGroupId)
			if err != nil {
				model.Log.Error(err)
				return nil
			}
			if id > 0 {
				signal.ThemeId = id
				signal.ThemeUrl = url
				signal.ThemeType = 2
			}
		}
		buf, err := json.Marshal(signal)
		if err == nil {
			systemMsg := group_m.GroupSystemMsg{MsgId: group_e.GroupEditProfileSignal, Source: externalId, Content: string(buf)}
			signal_s.SendSignalMsg(model, imGroupId, systemMsg, false)
		}
	}
	return err1
}

//增加群组自定义主题
func (s *GroupService) AddGroupCustomTheme(userId mysql.ID, imGroupId string, picUrl string) (uint64, string, error) {
	var themeId uint64 = 0
	var themeUrl string = ""
	return themeId, themeUrl, s.svc.Transactional(func() error {
		model := domain.CreateModel(s.svc.CtxAndDb)
		groupCustomTheme, err := group_m.AddGroupCustomTheme(model, userId, imGroupId, picUrl)
		if err != nil {
			return err
		}
		//将group_info的theme_id设置为0
		//修改数据,然后数据持久化,
		g := group_m.GroupInfo{
			ThemeId: 0,
		}
		fields := []string{"theme_id"}
		db := g.Update(model, imGroupId, fields)
		if db.Error != nil {
			return myerr.WrapErr(db.Error)
		}
		if err := groupCustomTheme.Persistent(); err != nil {
			return err
		}
		themeId = groupCustomTheme.ID
		themeUrl = groupCustomTheme.PicUrl
		return group_ev.PublishBuyGroupCustomTheme(model, &group_ev.BuyGroupCustomThemeEvent{
			GroupCustomThemeId: groupCustomTheme.ID,
			UserId:             userId,
		})
	})
}