package user

import (
	"encoding/json"
	"errors"
	"github.com/gin-gonic/gin"
	"github.com/silenceper/wechat/v2/miniprogram/auth"
	admin2 "hongze/hongze_yb/models/tables/admin"
	"hongze/hongze_yb/models/tables/rddp/session"
	"hongze/hongze_yb/models/tables/research_variety_tag_relation"
	"hongze/hongze_yb/models/tables/user_record"
	"hongze/hongze_yb/models/tables/wx_user"
	"hongze/hongze_yb/models/tables/wx_user_log"
	"hongze/hongze_yb/utils"
	"strconv"
	"time"
)

var ERR_NO_USER_RECORD = errors.New("用户关系没有入库")
var ERR_USER_NOT_BIND = errors.New("用户没有绑定")

type UserInfo struct {
	wx_user.WxUser
	RecordInfo *user_record.UserRecord
	LoginToken string
}

// GetWxUserItemByOpenId 通过openid获取用户信息
func GetWxUserItemByOpenId(openid string) (userInfo UserInfo, err error) {
	//通过openid获取用户关联信息
	userRecord, e := user_record.GetByOpenID(openid)
	if e != nil {
		if e == utils.ErrNoRow {
			err = ERR_NO_USER_RECORD
			return
		}
		err = e
		return
	}

	//该openid在系统中没有关联关系
	if userRecord == nil {
		err = ERR_NO_USER_RECORD
		return
	}

	//该openid没有绑定用户
	if userRecord.UserID <= 0 {
		err = ERR_USER_NOT_BIND
		item := new(wx_user.WxUser)
		//格式化返回用户数据
		userInfo = formatWxUserAndUserRecord(item, userRecord)
		return
	}

	//获取用户信息
	item, wxUserErr := wx_user.GetByUserId(userRecord.UserID)
	if wxUserErr != nil {
		err = wxUserErr

		//如果是找不到数据,那么可能是该用户被删除了,但是user_record没有删除对应的关系
		if wxUserErr == utils.ErrNoRow {
			//用户被删除了,但是user_record没有删除对应的关系,那么去解除绑定
			userUnbindErr := user_record.UnBindUserRecordByOpenid(openid)
			if userUnbindErr != nil {
				err = userUnbindErr
				return
			}
			//返回状态为 用户未绑定 逻辑代码
			err = ERR_USER_NOT_BIND
			item := new(wx_user.WxUser)
			//格式化返回用户数据
			userInfo = formatWxUserAndUserRecord(item, userRecord)
			return
		}
		return
	}
	//格式化返回用户数据
	userInfo = formatWxUserAndUserRecord(item, userRecord)
	return
}

// GetWxUserItemByUserId 根据用户id和平台id获取用户信息
func GetWxUserItemByUserId(userId, platform int) (userInfo UserInfo, err error) {
	//获取用户信息
	wxUser, err := wx_user.GetByUserId(userId)
	if err != nil {
		return
	}
	//格式化返回用户数据
	userInfo = formatWxUser(wxUser, platform)
	return
}

// GetWxUserItemByEmail 根据用户邮箱和平台id获取用户信息
func GetWxUserItemByEmail(email string, platform int) (userInfo UserInfo, err error) {
	//获取用户信息
	wxUser, err := wx_user.GetByEmail(email)
	if err != nil {
		return
	}
	//格式化返回用户数据
	userInfo = formatWxUser(wxUser, platform)
	return
}

// GetWxUserItemByMobile 根据用户手机号和平台id获取用户信息
func GetWxUserItemByMobile(mobile string, platform int) (userInfo UserInfo, err error) {
	//获取用户信息
	wxUser, err := wx_user.GetByMobile(mobile)
	if err != nil {
		return
	}
	//格式化返回用户数据
	userInfo = formatWxUser(wxUser, platform)
	return
}

// GetWxUserItemByUnionId 根据用户unionid和平台id获取用户信息
func GetWxUserItemByUnionId(unionId string, platform int) (userInfo UserInfo, err error) {
	// 获取用户信息
	userRecord, userRecordErr := user_record.GetByUnionID(unionId, platform)
	if userRecordErr != nil {
		if userRecordErr == utils.ErrNoRow {
			err = ERR_NO_USER_RECORD
			return
		} else {
			err = userRecordErr
			return
		}
	}

	// 该union在系统中没有关联关系
	if userRecord == nil {
		err = ERR_NO_USER_RECORD
		return
	}

	// 该openid没有绑定用户
	if userRecord.UserID <= 0 {
		err = ERR_USER_NOT_BIND
		item := new(wx_user.WxUser)
		//格式化返回用户数据
		userInfo = formatWxUserAndUserRecord(item, userRecord)
		return
	}

	item, wxUserErr := wx_user.GetByUserId(userRecord.UserID)
	if wxUserErr != nil {
		err = wxUserErr

		// 如果是找不到数据,那么可能是该用户被删除了,但是user_record没有删除对应的关系
		if wxUserErr == utils.ErrNoRow {
			// 用户被删除了,但是user_record没有删除对应的关系,那么去解除绑定
			userUnbindErr := user_record.UnBindUserRecordByUnionId(unionId, platform)
			if userUnbindErr != nil {
				err = userUnbindErr
				return
			}
			// 返回状态为用户未绑定
			err = ERR_USER_NOT_BIND
			item := new(wx_user.WxUser)
			// 格式化返回用户数据
			userInfo = formatWxUserAndUserRecord(item, userRecord)
			return
		}
		return
	}
	// 格式化返回用户数据
	userInfo = formatWxUserAndUserRecord(item, userRecord)

	return
}

// GetFirstWxUserItemByUnionId 根据用户unionid获取最小平台的用户信息(已经绑定了user_id的)
func GetFirstWxUserItemByUnionId(unionId string) (userInfo UserInfo, err error) {
	// 获取用户信息
	userRecord, userRecordErr := user_record.GetFirstByUnionID(unionId)
	if userRecordErr != nil {
		if userRecordErr == utils.ErrNoRow {
			err = ERR_NO_USER_RECORD
			return
		} else {
			err = userRecordErr
			return
		}
	}

	// 该union在系统中没有关联关系
	if userRecord == nil {
		err = ERR_NO_USER_RECORD
		return
	}

	// 该openid没有绑定用户
	if userRecord.UserID <= 0 {
		err = ERR_USER_NOT_BIND
		item := new(wx_user.WxUser)
		//格式化返回用户数据
		userInfo = formatWxUserAndUserRecord(item, userRecord)
		return
	}

	item, wxUserErr := wx_user.GetByUserId(userRecord.UserID)
	if wxUserErr != nil {
		err = wxUserErr

		// 如果是找不到数据,那么可能是该用户被删除了,但是user_record没有删除对应的关系
		if wxUserErr == utils.ErrNoRow {
			// 用户被删除了,但是user_record没有删除对应的关系,那么去解除绑定
			userUnbindErr := user_record.UnBindUserRecordByUnionId(unionId, int(userRecord.CreatePlatform))
			if userUnbindErr != nil {
				err = userUnbindErr
				return
			}
			// 返回状态为用户未绑定
			err = ERR_USER_NOT_BIND
			item := new(wx_user.WxUser)
			// 格式化返回用户数据
			userInfo = formatWxUserAndUserRecord(item, userRecord)
			return
		}
		return
	}
	// 格式化返回用户数据
	userInfo = formatWxUserAndUserRecord(item, userRecord)

	return
}

// formatWxUserAndUserRecord 通过用户 关系表记录  和  用户记录  格式化返回 用户数据
func formatWxUserAndUserRecord(wxUser *wx_user.WxUser, userRecord *user_record.UserRecord) (userInfo UserInfo) {
	wxUser.OpenID = userRecord.OpenID
	wxUser.UnionID = userRecord.UnionID
	//wxUser.NickName = userRecord.NickName
	//wxUser.RealName = userRecord.RealName
	//wxUser.BindAccount = userRecord.BindAccount
	//wxUser.Headimgurl = userRecord.Headimgurl

	wxUserJson, _ := json.Marshal(wxUser)
	_ = json.Unmarshal(wxUserJson, &userInfo)
	userInfo.RecordInfo = userRecord
	return
}

// formatWxUser 通过用户 用户记录  和  来源平台  格式化返回 用户数据
func formatWxUser(wxUser *wx_user.WxUser, platform int) (userInfo UserInfo) {
	//根据用户id和平台id获取用户关系
	userRecord, userRecordErr := user_record.GetByUserId(int(wxUser.UserID), platform)
	if userRecordErr != nil {
		if userRecordErr != utils.ErrNoRow {
			return
		}
	}

	//该openid在系统中没有关联关系
	if userRecord == nil {
		wxUserJson, _ := json.Marshal(wxUser)
		_ = json.Unmarshal(wxUserJson, &userInfo)
		return
	} else {
		userInfo = formatWxUserAndUserRecord(wxUser, userRecord)
	}
	return
}

// WxLogin 微信登录
func WxLogin(wxPlatform int, wxSession auth.ResCode2Session) (token string, userId int, isBind bool, err error) {
	openId := wxSession.OpenID
	unionId := wxSession.UnionID
	sessionKey := wxSession.SessionKey

	needUpdateSessionKey := true //是否更新sessionKey

QUERY_WX_USER:
	wxUser, wxUserErr := GetWxUserItemByOpenId(openId)
	if wxUserErr == ERR_NO_USER_RECORD { //没有用户openid记录
		_, recordErr := AddUserRecord(openId, unionId, "", "", "", "", "", "", sessionKey, wxPlatform, 0, 0)
		//如果插入失败,那么直接将错误信息返回
		if recordErr != nil {
			err = recordErr
			return
		}
		needUpdateSessionKey = false //因为是新增用户微信信息,所以不需要更新sessionKey的数据了

		//插入成功后,需要重新查询该用户,并进入下面的逻辑
		goto QUERY_WX_USER
	} else if wxUserErr == ERR_USER_NOT_BIND {
		// 未绑定则去查询unionId是否已经绑定了用户(其他平台,不区分平台),有相应的手机号邮箱信息则自动绑定
		//platformUser, platformErr := GetFirstWxUserItemByUnionId(unionId)
		//if platformErr == nil {
		//	// 当公众号用户存在时
		//	if platformUser.Mobile != "" || platformUser.Email != "" {
		//		// 有手机号或邮箱则绑定信息则自动绑定并新增wx_user
		//		countryCode := 0
		//		if platformUser.CountryCode != "" {
		//			countryCode, _ = strconv.Atoi(platformUser.CountryCode)
		//		}
		//		tempToken, tempUser, tempErr, errMsg := BindWxUser(openId, platformUser.Mobile, platformUser.Email, "", 3, countryCode, 1)
		//		if tempErr != nil {
		//			err = errors.New("自动绑定公众号用户失败,Err:" + tempErr.Error() + ", errMsg:" + errMsg)
		//			return
		//		}
		//		token = tempToken
		//		userId = int(tempUser.UserID)
		//		isBind = true
		//		return
		//	}
		//}
	} else if wxUserErr != nil {
		err = wxUserErr
		return
	}

	//更新微信用户的sessionKey
	if needUpdateSessionKey {
		_ = user_record.ModifySessionKeyByOpenid(openId, sessionKey)
	}

	// 如果已经登录注册绑定的情况下/或者首次登录且为弘则研究公众号用户
	if wxUserErr == nil {
		userId = int(wxUser.UserID)

		// 如果账户有绑定了手机号或者邮箱,那么标记为已绑定
		if wxUser.Mobile != "" || wxUser.Email != "" {
			isBind = true
		}
	}

	//获取登录token
	tokenItem, tokenErr := session.GetTokenByOpenId(openId)
	if tokenErr != nil && tokenErr != utils.ErrNoRow {
		err = errors.New("登录失败,获取token失败:" + tokenErr.Error())
		return
	}

	if tokenErr != nil && tokenErr == utils.ErrNoRow {
		timeUnix := time.Now().Unix()
		timeUnixStr := strconv.FormatInt(timeUnix, 10)
		token = utils.MD5(openId) + utils.MD5(timeUnixStr)
		//新增session
		{
			sessionItem := &session.Session{
				OpenID:          openId,
				UserID:          int64(userId),
				CreatedTime:     time.Now(),
				LastUpdatedTime: time.Now(),
				ExpireTime:      time.Now().AddDate(0, 3, 0),
				AccessToken:     token,
			}
			sessionErr := sessionItem.Create()
			if err != nil {
				err = errors.New("登录失败,新增用户session信息失败:" + sessionErr.Error())
				return
			}
		}
	} else {
		token = tokenItem.AccessToken
		//如果联系人编号不为空,且联系人编号与session里面的联系人编号不一致的时候,需要做session变更
		//if userId > 0 && tokenItem.UserID != int64(userId) {
		//	_ = tokenItem.UpdateSession(int64(userId), time.Now().AddDate(0, 1, 0))
		//}

		//if userId > 0 {
		//}
		_ = tokenItem.UpdateSession(int64(userId), time.Now().AddDate(0, 1, 0))
	}

	//新增登录日志
	{
		loginLog := &wx_user_log.WxUserLog{
			UserID:     userId,
			OpenID:     openId,
			UnionID:    unionId,
			CreateTime: time.Now(),
			Handle:     "yb_login",
			Remark:     token,
		}
		go loginLog.Create()
	}
	return
}

// AddUserRecord 添加第三方用户(微信)记录
func AddUserRecord(openId, unionId, nickName, realName, province, city, country, headimgurl, sessionKey string, platform, sex, subscribe int) (userRecordInfo *user_record.UserRecord, err error) {
	find, err := user_record.GetByOpenID(openId)
	if err == nil {
		userRecordInfo = find
		return
	}
	if err != utils.ErrNoRow {
		return
	}

	userRecordInfo = &user_record.UserRecord{
		OpenID:         openId,  //用户open_id
		UnionID:        unionId, //用户union_id
		Subscribe:      int8(subscribe),
		NickName:       nickName,       //用户昵称,最大长度:32
		RealName:       realName,       //用户实际名称,最大长度:32
		Sex:            int64(sex),     //普通用户性别,1为男性,2为女性
		Province:       province,       //普通用户个人资料填写的省份,最大长度:30
		City:           city,           //普通用户个人资料填写的城市,最大长度:30
		Country:        country,        //国家,如中国为CN,最大长度:30
		Headimgurl:     headimgurl,     //用户第三方(微信)头像,最大长度:512
		CreateTime:     time.Now(),     //创建时间,关系添加时间、用户授权时间
		CreatePlatform: int8(platform), //注册平台,1:日度点评公众号,2:管理后台,3:pc端网站,4:查研观向小程序;默认:1
		SessionKey:     sessionKey,     //微信小程序会话密钥,最大长度:255
	}
	err = userRecordInfo.Create()
	return
}

// GetInfoByClaims 从Claims中获取用户信息
func GetInfoByClaims(c *gin.Context) (userInfo UserInfo) {
	//获取jwt数据失败
	claims, _ := c.Get("userInfo")
	userInfo = claims.(UserInfo)
	return
}

// GetAdminByUserInfo 判断当前用户是否为内部人员
func GetAdminByUserInfo(userInfo UserInfo) (ok bool, adminInfo *admin2.Admin, err error) {
	mobile := userInfo.Mobile
	if mobile == "" {
		// 用户有可能是通过邮箱登录
		return
	}
	if userInfo.CompanyID != utils.HzCompanyId {
		return
	}
	adminInfo, err = admin2.GetAdminByMobile(mobile)
	if err != nil {
		if err == utils.ErrNoRow {
			err = nil
			return
		}
		return
	}
	if adminInfo.Enabled != 1 {
		return
	}
	ok = true

	return
}

// GetResearcherByUserInfo 判断当前用户是否为研究员-以是否有研究分组为判断标准
func GetResearcherByUserInfo(userInfo UserInfo) (ok bool, adminInfo *admin2.Admin, err error) {
	mobile := userInfo.Mobile
	if mobile == "" {
		// 用户有可能是通过邮箱登录
		return
	}
	if userInfo.CompanyID != utils.HzCompanyId {
		return
	}
	adminInfo, err = admin2.GetAdminByMobile(mobile)
	if err != nil {
		if err == utils.ErrNoRow {
			err = nil
			return
		}
		return
	}
	if adminInfo.Enabled != 1 {
		return
	}
	researchGroupList, e := research_variety_tag_relation.GetResearchVarietyTagRelationByAdminId(int(adminInfo.AdminID))
	if e != nil {
		err = e
		return
	}
	if len(researchGroupList) > 0 {
		ok = true
	}

	return
}

// GetUserInfoByToken 通过token获取用户信息
func GetUserInfoByToken(token string) (userInfo UserInfo, err error) {
	sessionInfo, e := session.GetTokenByToken(token)
	if e != nil {
		err = errors.New("找不到对应session")
		return
	}
	if sessionInfo.SessionID <= 0 {
		err = errors.New("找不到对应session")
		return
	}
	if sessionInfo.OpenID != "" {
		u, e := GetWxUserItemByOpenId(sessionInfo.OpenID)
		if e != nil {
			err = errors.New("用户记录不存在或未绑定")
			return
		}
		userInfo = u
	} else {
		// PC端
		u, e := GetWxUserItemByUserId(int(sessionInfo.UserID), utils.USER_RECORD_PLATFORM_PC)
		if e != nil {
			err = errors.New("用户PC记录不存在或未绑定")
			return
		}
		userInfo = u
	}
	return
}