package service

import (
	"encoding/json"
	"errors"
	"pure-admin/global"
	"pure-admin/model"
	"pure-admin/model/request"
	"pure-admin/utils"
	"time"
)

//@author: [piexlmax](https://github.com/piexlmax)
//@function: CreateUser
//@description: 创建User记录
//@param: user model.User
//@return: err error

func CreateUser(user model.User) (err error) {
	err = global.MG_DB.Create(&user).Error
	return err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: DeleteUser
//@description: 删除User记录
//@param: user model.User
//@return: err error

func DeleteUser(user model.User) (err error) {
	err = global.MG_DB.Delete(&user).Error
	return err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: DeleteUserByIds
//@description: 批量删除User记录
//@param: ids request.IdsReq
//@return: err error

func DeleteUserByIds(ids request.IdsReq) (err error) {
	err = global.MG_DB.Delete(&[]model.User{}, "id in (?)", ids.Ids).Error
	return err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: UpdateUser
//@description: 更新User记录
//@param: user *model.User
//@return: err error

func UpdateUser(user model.User) (err error) {
	if user.Password != "" {
		user.Password = utils.MD5V([]byte(user.Password))
	}
	err = global.MG_DB.Updates(&user).Error
	return err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: GetUser
//@description: 根据id获取User记录
//@param: id uint
//@return: err error, user model.User

func GetUser(uuid string) (err error, user model.UserSimple) {
	var (
		dictData []model.SysDictData
	)
	err = global.MG_DB.Where("uuid = ?", uuid).First(&user).Error
	if err != nil {
		return
	}
	err = global.MG_DB.Model(&model.SysDictData{}).Where("dict_type=?", "release_channel").Find(&dictData).Error
	if err != nil {
		return errors.New("获取用户失败"), user
	}
	platformsC := make([]model.Platform, 0)
	for i := 0; i < len(dictData); i++ {
		platformsC = append(platformsC, model.Platform{
			Platform: dictData[i].Value,
		})
	}
	if user.Platform != "" {
		var platforms []model.Platform
		json.Unmarshal([]byte(user.Platform), &platforms)
		for i := 0; i < len(platforms); i++ {
			for j := 0; j < len(platformsC); j++ {
				if platforms[i].Platform == platformsC[j].Platform {
					platformsC[j].IsAuth = platforms[i].IsAuth
					platformsC[j].Url = platforms[i].Url
					platformsC[j].Image = platforms[i].Image
				}
			}
		}
		user.Platforms = platformsC
	} else {
		user.Platforms = platformsC
	}
	return
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: GetUserInfoList
//@description: 分页获取User记录
//@param: info request.UserSearch
//@return: err error, list interface{}, total int64

func GetUserInfoList(info request.UserSimpleSearch, appid string) (err error, list interface{}, total int64) {
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	// 创建db
	db := global.MG_DB.Model(&model.User{})
	db = db.Where("appid = ?", appid)
	var users []model.UserSimple
	// 如果有条件搜索 下方会自动创建搜索语句
	if info.Type != "" {
		db = db.Where("type = ?", info.Type)
	} else {
		db = db.Where("type=?", "customer")
	}
	if info.StartTime != "" {
		db = db.Where("created_at >= ?", info.StartTime)
	}
	if info.EndTime != "" {
		db = db.Where("created_at < ?", info.EndTime)
	}
	if info.Phone != "" {
		db = db.Where("phone = ?", info.Phone)
	}
	if info.Email != "" {
		db = db.Where("email = ?", info.Email)
	}
	if info.NickName != "" {
		db = db.Where("nick_name like ?", "%"+info.NickName+"%")
	}
	err = db.Count(&total).Error
	err = db.Limit(limit).Offset(offset).Find(&users).Error
	if err != nil {
		return err, nil, 0
	}
	var userIds []string
	for i := 0; i < len(users); i++ {
		users[i].CreatedStr = users[i].CreatedAt.Format(utils.DateTimeFormat)
		userIds = append(userIds, users[i].UUID.String())
	}
	if info.Type == "influencer" {
		var (
			dictData []model.SysDictData
		)
		err = global.MG_DB.Model(&model.SysDictData{}).Where("type_code=?", "release_channel").Find(&dictData).Error
		if err != nil {
			return errors.New("获取用户失败"), users, total
		}
		for i := 0; i < len(users); i++ {
			var platforms []model.Platform
			err = json.Unmarshal([]byte(users[i].Platform), &platforms)
			if err != nil {
				for i := 0; i < len(dictData); i++ {
					platforms = append(platforms, model.Platform{
						Platform:     dictData[i].Value,
						PlatformName: dictData[i].Label,
					})
				}
				// platforms = append(platforms, u.Platform)
			}
			for j := 0; j < len(platforms); j++ {
				for k := 0; k < len(dictData); k++ {
					if platforms[j].Platform == dictData[k].Value {
						platforms[j].PlatformName = dictData[k].Label
					}
				}
			}
			err = nil
			users[i].Platforms = platforms
		}
	}
	// 累计订单数
	var orderNumMap map[string]model.DtStatisticOrder
	orderNumMap, err = getStatisticsOrderUsers(userIds, "", nil)
	for i := 0; i < len(users); i++ {
		if val, ok := orderNumMap[users[i].UUID.String()]; ok {
			users[i].OrderCount = val.OrderNum
		}
	}
	// 退款数
	var postSaleNumMap map[string]int64
	now := time.Now()
	start := now.AddDate(0, 0, -6).Format("20060102")
	end := now.AddDate(0, 0, 1).Format("20060102")
	postSaleNumMap, err = getOrderPostSaleCountList(&request.SearchOrderPostSale{UserIds: userIds, CreatedAtStart: start, CreatedAtEnd: end})
	for i := 0; i < len(users); i++ {
		if val, ok := postSaleNumMap[users[i].UUID.String()]; ok {
			users[i].RefundCount = val
		}
	}
	return err, users, total
}

func GetSysUserInfoList(info request.UserSimpleSearch, appid string) (err error, list interface{}, total int64) {
	var (
		authorityIds = make([]string, 0)
		authorities  []model.SysAuthority
	)
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	db := global.MG_DB.Model(&model.User{})
	db = db.Where("appid=? and type=?", appid, "admin")
	if info.NickName != "" {
		db = db.Where("nick_name LIKE ?", "%"+info.NickName+"%")
	}
	if info.Username != "" {
		db = db.Where("username LIKE ?", "%"+info.Username+"%")
	}
	if info.Phone != "" {
		db = db.Where("phone LIKE ?", "%"+info.Phone+"%")
	}
	if info.IDForbidden != "" {
		db = db.Where("id_forbidden = ?", info.IDForbidden)
	}
	var userList []model.UserSimple
	err = db.Count(&total).Error
	err = db.Limit(limit).Offset(offset).Find(&userList).Error
	if err != nil {
		return err, nil, 0
	}
	for k, _ := range userList {
		e := Casbin()
		res := e.GetRolesForUserInDomain(userList[k].UUID.String(), appid)
		if len(res) > 0 {
			authorityIds = append(authorityIds, res...)
		}
	}
	if len(authorityIds) > 0 {
		err = global.MG_DB.Where("authority_id IN ?", authorityIds).Find(&authorities).Error
	}
	for k, _ := range userList {
		authorities1 := make([]model.SysAuthority, 0)
		for _, v := range authorities {
			if userList[k].AuthorityID == v.AuthorityId {
				authorities1 = append(authorities1, v)
			}
		}
		userList[k].Authorities = authorities1
	}
	return err, userList, total
}

func GetUserInfo(uuid, appid string) (err error, user model.User) {
	var (
		reqUser     model.User
		authorities []model.SysAuthority
	)
	err = global.MG_DB.First(&reqUser, "uuid = ?", uuid).Error
	if err != nil {
		return err, reqUser
	}
	e := Casbin()
	res := e.GetRolesForUserInDomain(uuid, appid)
	if len(res) > 0 {
		err = global.MG_DB.Where("authority_id IN ?", res).Find(&authorities).Error
	} else {
		err = errors.New("该用户未分配角色")
	}
	for _, v := range authorities {
		if reqUser.AuthorityID == v.AuthorityId {
			reqUser.Authority = v
			break
		}
	}
	reqUser.Authorities = authorities
	return err, reqUser
}

func GetPlatformAuthList(info request.PlatformAuthSearch) (err error, list interface{}, total int64) {
	var (
		platformAuths     []model.PlatformAuthSimple
		userIds           []string
		checkUserIds      []string
		checkUsers        []model.UserSimple
		users             []model.UserSimple
		wallet            []model.Wallet
		account           []model.Account
		dictData          []model.SysDictData
		tag_relation      []model.TagRelation
		tags              []model.Tags
		userPlatformAuths []model.PlatformAuthSimple
	)
	err = global.MG_DB.Model(&model.SysDictData{}).Where("type_code=?", "release_channel").Find(&dictData).Error
	if err != nil {
		return errors.New("获取用户失败"), platformAuths, total
	}
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	// 创建db
	db := global.MG_DB.Model(&model.PlatformAuth{})
	if info.Platform != "" {
		db = db.Where("platform = ?", info.Platform)
	}
	if info.Status != "" {
		db = db.Where("status = ?", info.Status)
	}
	if info.StartTime != "" && info.EndTime != "" {
		db = db.Where("created_at BETWEEN ? AND ?", info.StartTime, info.EndTime)
	}
	if info.Phone != "" {
		db = db.Joins("inner join user on user.uuid=platform_auth.user_id and user.phone = ?", info.Phone)
	}
	if info.Email != "" {
		db = db.Joins("inner join user on user.uuid=platform_auth.user_id and user.email = ?", info.Email)
	}
	if info.NickName != "" {
		db = db.Joins("inner join user on user.uuid=platform_auth.user_id and user.nick_name like ?", "%"+info.NickName+"%")
	}
	// 如果有条件搜索 下方会自动创建搜索语句
	err = db.Count(&total).Error
	err = db.Limit(limit).Offset(offset).Order("id desc").Find(&platformAuths).Error
	for _, v := range platformAuths {
		userIds = append(userIds, v.UserID)
	}
	err = global.MG_DB.Where("uuid IN ?", userIds).Find(&users).Error
	err = global.MG_DB.Where("user_id IN ?", userIds).Find(&userPlatformAuths).Error
	err = global.MG_DB.Raw("SELECT * FROM (SELECT *,ROW_NUMBER() OVER (PARTITION BY user_id,platform ORDER BY updated_at DESC) AS rn FROM platform_auth WHERE user_id in (?) AND `status` !=0) AS subquery WHERE rn=1", userIds).Scan(&userPlatformAuths).Error
	for _, v := range userPlatformAuths {
		checkUserIds = append(checkUserIds, v.CheckUser)
	}
	err = global.MG_DB.Where("uuid IN ?", checkUserIds).Find(&checkUsers).Error
	err = global.MG_DB.Where("user_id IN ?", userIds).Find(&wallet).Error
	err = global.MG_DB.Where("user_id IN ?", userIds).Find(&account).Error
	err = global.MG_DB.Where("relation_id IN ?", userIds).Find(&tag_relation).Error
	var tagIds []uint
	for _, v := range tag_relation {
		tagIds = append(tagIds, v.TagId)
	}
	err = global.MG_DB.Where("id IN ?", tagIds).Find(&tags).Error
	for i, v := range platformAuths {
		for k := 0; k < len(dictData); k++ {
			if platformAuths[i].Platform.Platform == dictData[k].Value {
				platformAuths[i].PlatformName = dictData[k].Label
			}
		}
		var tagDesc = make([]model.TagRelationDesc, 0)
		for j := 0; j < len(tag_relation); j++ {
			if v.UserID == tag_relation[j].RelationId {
				for k := 0; k < len(tags); k++ {
					if tag_relation[j].TagId == tags[k].ID {
						tagDesc = append(tagDesc, model.TagRelationDesc{
							ID:   tags[k].ID,
							Name: tags[k].Value,
						})
					}
				}
			}
		}
		platformAuths[i].TagRelationDesc = tagDesc
		for _, u := range users {
			if v.UserID == u.UUID.String() {
				var platforms []model.Platform
				platformAuths[i].User = u
				err = json.Unmarshal([]byte(u.Platform), &platforms)
				if err != nil {
					for i := 0; i < len(dictData); i++ {
						platforms = append(platforms, model.Platform{
							Platform:     dictData[i].Value,
							PlatformName: dictData[i].Label,
						})
					}
					// platforms = append(platforms, u.Platform)
				}
				for j := 0; j < len(platforms); j++ {
					for k := 0; k < len(dictData); k++ {
						if platforms[j].Platform == dictData[k].Value {
							platforms[j].PlatformName = dictData[k].Label
						}
					}
					for k := 0; k < len(userPlatformAuths); k++ {
						if userPlatformAuths[k].UserID == u.UUID.String() && userPlatformAuths[k].Platform.Platform == platforms[j].Platform {
							if platforms[j].AuthMsg == "" {
								platforms[j].AuthMsg = userPlatformAuths[k].AuthMsg
							}
							for l := 0; l < len(checkUsers); l++ {
								if userPlatformAuths[k].CheckUser == checkUsers[l].UUID.String() {
									platforms[j].CheckUser = checkUsers[l].NickName
								}
							}
						}
					}
				}
				err = nil
				platformAuths[i].User.Platforms = platforms
				break
			}
		}
		for _, w := range wallet {
			if v.UserID == w.UserID {
				platformAuths[i].User.Wallet = w
				break
			}
		}
		for _, a := range account {
			if v.UserID == a.UserID {
				platformAuths[i].User.Account = append(platformAuths[i].User.Account, a)
			}
		}
	}
	return err, platformAuths, total
}

func CheckPlatformAuth(info *request.PlatformAuthCheck, userID string) (err error) {
	var (
		platformAuth model.PlatformAuth
		user         model.User
		platforms    []model.Platform
		uMap         = make(map[string]interface{})
	)
	err = global.MG_DB.First(&platformAuth, "id = ?", info.ID).Error
	if err != nil {
		return err
	}
	if platformAuth.Status != "0" {
		return errors.New("该认证已审核")
	}
	err = global.MG_DB.First(&user, "uuid = ?", platformAuth.UserID).Error
	if err != nil {
		return err
	}
	json.Unmarshal([]byte(user.Platform), &platforms)
	err = global.MG_DB.Model(&platformAuth).Updates(map[string]interface{}{"status": info.Status, "check_user": userID, "auth_msg": info.AuthMsg}).Error
	if err != nil {
		return err
	}
	for i, v := range platforms {
		if v.Platform == platformAuth.Platform.Platform {
			if info.Status == "1" {
				platforms[i].IsAuth = true
				platforms[i].AuthTime = time.Now().Format(utils.DateTimeFormat)
			} else {
				platforms[i].IsAuth = false
				platforms[i].Url = ""
				platforms[i].Image = ""
			}
			break
		}
	}
	uMap["is_auth"] = false
	for _, v := range platforms {
		if v.IsAuth {
			uMap["is_auth"] = true
			break
		} else {
			uMap["is_auth"] = false
		}
	}
	platformsByte, _ := json.Marshal(platforms)
	uMap["platform"] = string(platformsByte)
	err = global.MG_DB.Model(&user).Updates(uMap).Error
	return
}

func UpdateUserStatus(info *request.UserStatus, appid, userID string) (err error) {
	var (
		user model.User
		uMap = make(map[string]interface{})
	)
	err = global.MG_DB.First(&user, "uuid = ? and appid=?", info.UserID, appid).Error
	if err != nil {
		return err
	}
	if user.IDForbidden == info.IDForbidden {
		return errors.New("该用户已是该状态")
	}
	if info.IDForbidden == true {
		uMap["id_forbidden"] = 1
		uMap["forbidden_reason"] = info.ForbiddenReason
		uMap["forbidden_time"] = time.Now()
		uMap["forbidden_operation"] = userID
		_, jwtStr := GetRedisJWT(user.Username)
		if jwtStr != "" {
			JsonInBlacklist(model.JwtBlacklist{Jwt: jwtStr})
		}
	} else {
		uMap["id_forbidden"] = 0
		uMap["forbidden_reason"] = ""
		uMap["forbidden_time"] = nil
		uMap["forbidden_operation"] = userID
	}
	err = global.MG_DB.Model(&user).Where("uuid = ? and appid=?", info.UserID, appid).Updates(uMap).Error
	if err != nil {
		return err
	}
	return
}

func getUserSimpleList(ut string, uuids []string) ([]model.UserSimple, error) {
	var (
		err    error
		result []model.UserSimple
	)
	err = global.MG_DB.Model(&model.User{}).Select("uuid,nick_name,avatar,phone,platform,tags").Where("`type` = ? AND uuid IN (?)", ut, uuids).Find(&result).Error
	if err != nil {
		return nil, err
	}
	return result, nil
}
func getUserViewMap(uuids ...string) (map[string]model.UserView, error) {
	var (
		err    error
		list   []model.UserView
		result = make(map[string]model.UserView)
	)
	err = global.MG_DB.Model(&model.User{}).Select("uuid,email").Where("uuid IN (?)", uuids).Find(&list).Error
	if err != nil {
		return nil, err
	}
	for _, userView := range list {
		result[userView.UUID.String()] = userView
	}
	return result, nil
}