package user

import (
	"context"
	"errors"
	"fmt"
	"hongze/hongze_yb/global"
	"hongze/hongze_yb/models/tables/rddp/msg_code"
	"hongze/hongze_yb/models/tables/rddp/session"
	"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"
)

// BindWxUser 用户注册/绑定
func BindWxUser(openid, mobile, email, code string, bindType, areaNum, registerPlatform int) (token string, userInfo UserInfo, err error, errMsg string) {
	switch bindType {
	case 1: //手机号
		_, tmpErr := msg_code.GetMsgCode(mobile, code)
		if tmpErr != nil {
			if err == utils.ErrNoRow {
				err = errors.New("校验验证码失败，Err:" + tmpErr.Error())
				errMsg = "校验验证码失败"
				return
			} else {
				err = errors.New("校验验证码失败，Err:" + tmpErr.Error())
				errMsg = "验证码错误,请重新输入"
				return
			}
		}
	case 2: //邮箱
		_, tmpErr := msg_code.GetMsgCode(email, code)
		if tmpErr != nil {
			if err == utils.ErrNoRow {
				err = errors.New("校验验证码失败，Err:" + tmpErr.Error())
				errMsg = "校验验证码失败"
				return
			} else {
				err = errors.New("校验验证码失败，Err:" + tmpErr.Error())
				errMsg = "验证码错误,请重新输入"
				return
			}
		}
	case 3: //微信授权登录（无需校验）

	default:
		err = errors.New("无效的绑定方式,bindType:" + strconv.Itoa(bindType))
		errMsg = "无效的绑定方式"
		return
	}

	userInfo, errMsg, err = bindWxUser(openid, mobile, email, areaNum, registerPlatform)

	if err != nil {
		if errMsg == `` {
			errMsg = "绑定失败：" + err.Error()
		}
		err = errors.New("BindWxUser绑定失败: " + err.Error())
		return
	}

	sessionItem, err := session.GetTokenByOpenId(userInfo.OpenID)
	if err != nil && err != utils.ErrNoRow {
		errMsg = "登录失败"
		err = errors.New("登录失败，获取token失败:" + err.Error())
		return
	}

	if sessionItem == nil || (err != nil && err == utils.ErrNoRow) {
		timeUnix := time.Now().Unix()
		timeUnixStr := strconv.FormatInt(timeUnix, 10)
		token = utils.MD5(userInfo.OpenID) + utils.MD5(timeUnixStr)
		//新增session
		{
			sessionInfo := &session.Session{
				OpenID:          userInfo.OpenID,
				UserID:          int64(userInfo.UserID),
				CreatedTime:     time.Now(),
				LastUpdatedTime: time.Now(),
				ExpireTime:      time.Now().AddDate(0, 1, 0),
				AccessToken:     token,
			}
			tmpErr := sessionInfo.Create()
			if tmpErr != nil {
				errMsg = "登录失败"
				err = errors.New("登录失败，新增用户session信息失败:" + tmpErr.Error())
				return
			}
		}
	} else {
		token = sessionItem.AccessToken
		_ = sessionItem.UpdateSession(int64(userInfo.UserID), time.Now().AddDate(0, 1, 0))
	}
	err = nil

	tmpErr := wx_user.ModifyFirstLogin(userInfo.UserID)
	if tmpErr != nil {
		fmt.Println("变更联系人是否第一次登录失败，ERR:", tmpErr)
		return
	}

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

// bindWxUser 用户注册/绑定
func bindWxUser(openid, mobile, email string, areaNum, registerPlatform int) (userInfo UserInfo, errMsg string, err error) {
	source := int8(utils.USER_RECORD_PLATFORM_YB) //绑定来源，1:微信端,2:pc网页端，3:查研观向小程序,4:每日咨询
	if mobile == "" && email == "" {
		err = errors.New("手机号或邮箱必填一个")
		return
	}
	var bindAccount string
	var wxUser *wx_user.WxUser
	needCreateWxUser := true

	//根据手机号获取用户信息
	if mobile != "" {
		tmpWxUser, wxUserErr := wx_user.GetByMobile(mobile)
		if wxUserErr != nil {
			if wxUserErr != utils.ErrNoRow {
				err = wxUserErr
				return
			}
		} else {
			needCreateWxUser = false
			wxUser = tmpWxUser
			bindAccount = mobile
		}
	}
	//根据邮箱获取用户信息
	if needCreateWxUser && email != "" {
		tmpWxUser, wxUserErr := wx_user.GetByEmail(email)
		if wxUserErr != nil {
			if wxUserErr != utils.ErrNoRow {
				err = wxUserErr
				return
			}
		} else {
			needCreateWxUser = false
			wxUser = tmpWxUser
			bindAccount = email
		}
	}

	//查询openid的第三方（微信）信息
	userRecord, err := user_record.GetByOpenID(openid)
	if err != nil {
		return
	}

	var userId int
	//如果查询出来的结果是空，那么需要新增用户
	if needCreateWxUser {
		key := "bind_wx_user:mobile:" + mobile + ":email:" + email
		isHas, _ := global.Redis.Exists(context.TODO(), key).Result()
		if isHas > 0 {
			err = errors.New("多次提交，请关闭页面重新进入")
			return
		}
		global.Redis.SetNX(context.TODO(), key, "ok", time.Second*300)
		addwxUser := &wx_user.WxUser{
			CompanyID:           1,
			CreatedTime:         time.Now(),
			FirstLogin:          1,
			Enabled:             1,
			RegisterPlatform:    int8(registerPlatform), //账号注册来源，注册平台,1:微信端,2:PC网页端
			RegisterTime:        time.Now(),
			Mobile:              mobile,
			Email:               email,
			IsRegister:          1,
			Source:              source,
			CountryCode:         strconv.Itoa(areaNum),
			OutboundMobile:      mobile,
			OutboundCountryCode: strconv.Itoa(areaNum),
		}

		addUserErr := addwxUser.Create()
		//添加完成，清除缓存
		_ = global.Redis.Del(context.TODO(), key)
		if addUserErr != nil {
			err = addUserErr
			return
		}
		userId = int(addwxUser.UserID)
		tmpWxUser, _ := wx_user.GetByUserId(userId)
		wxUser = tmpWxUser
	} else {
		userId = int(wxUser.UserID)
	}
	//如果存在该手机号/邮箱，那么需要校验
	if userRecord.UserID > 0 && userRecord.UserID != userId {
		err = errors.New(fmt.Sprint("用户已绑定其他账户,已绑定的用户编号：", userRecord.UserID, "，不允许重复绑定"))
		currUser, tmpErr := wx_user.GetByUserId(userRecord.UserID)
		if tmpErr != utils.ErrNoRow {
			currBindAccount := currUser.Mobile
			if currBindAccount == `` {
				currBindAccount = currUser.Email
			}
			errMsg = "微信已绑定其它账户：" + currBindAccount
		}
		return
	}

	// 未绑定
	if userRecord.UserID == 0 {
		// 校验该手机号/邮箱是否已绑定过微信, 若已绑定过则所有微信均进行解绑, 仅绑定当前微信
		repeats, e := user_record.GetRepeatBindAccount(bindAccount, userRecord.UnionID)
		if e != nil {
			err = fmt.Errorf("获取重复的绑定账号数失败, err: %s", e.Error())
			errMsg = "绑定异常"
			return
		}
		if len(repeats) > 0 {
			// 清除绑定关系
			if e = user_record.ClearRepeatBindAccount(bindAccount, userRecord.UnionID); e != nil {
				err = fmt.Errorf("重置重复的绑定账号失败, err: %s", e.Error())
				errMsg = "绑定异常"
				return
			}
			// 清除重复账号的session
			repeatOpenIds := make([]string, 0)
			for _, v := range repeats {
				repeatOpenIds = append(repeatOpenIds, v.OpenID)
			}
			if e = session.ClearRepeatBindAccountToken(repeatOpenIds); e != nil {
				err = fmt.Errorf("清除重复绑定账号Token失败, err: %v", e)
				errMsg = "绑定异常"
				return
			}
		}

		userRecord.BindAccount = bindAccount
		userRecord.UserID = userId
		var updateCols = []string{"UserID", "BindAccount"}
		if e = userRecord.Update(updateCols); e != nil {
			err = e
			return
		}
	}

	//如果当前该第三方用户信息的昵称为空串的话，那么需要去查询该用户的第一个绑定信息的数据作为来源做数据修复
	if userRecord.NickName == "" {
		oldUserRecord, err := user_record.GetUserThirdRecordByUserId(userId)
		if err == nil && oldUserRecord != nil {
			//如果该用户绑定的第一条数据的头像信息不为空串，那么就去做新数据的修复
			if oldUserRecord.NickName != "" {
				_ = userRecord.ModifyUserRecordInfo(oldUserRecord.NickName, oldUserRecord.Headimgurl, oldUserRecord.City, oldUserRecord.Province, oldUserRecord.Country, oldUserRecord.Sex)
			}
		}
	}

	//如果该用户 绑定注册状态 字段处于 未注册 的情况下，那么去修改该数据
	if wxUser.IsRegister == 0 {
		err = wxUser.ModifyWxUserRegisterStatus(1, source, time.Now())
		if err != nil {
			return
		}
	}

	if userRecord.UnionID != `` {
		tmpErr := user_record.ModifyUserIdByUnionId(userRecord.UnionID, userRecord.UserID)
		if tmpErr != nil {
			global.LOG.Info("通过用户unionId修改所有未绑定用户的id失败，Err:" + err.Error())
		}
	}

	//格式化用户数据
	userInfo = formatWxUserAndUserRecord(wxUser, userRecord)
	return
}
