package db

import (
	"applet/app/db/model"
	"applet/app/md"
	"applet/app/utils"
	"applet/app/utils/logx"
	"fmt"
	"strings"
	"xorm.io/xorm"
)

// UserisExistByUsernameAndPassword is usernameAndPassword exist
func UserisExistByUsernameAndPassword(Db *xorm.Engine, username, password, zone string) (*model.User, error) {
	var user model.User
	sess := Db.Where("(username = ? or phone=?) ", username, username)
	if zone != "" && zone != "86" {
		sess = sess.And("zone=?", zone)
	}
	has, err := sess.Get(&user)
	if err != nil || has == false {
		return nil, err
	}
	return &user, nil
}
func UserThirdPartyFindByID(Db *xorm.Engine, id interface{}) (*model.UserThirdParty, error) {
	var m model.UserThirdParty
	if has, err := Db.Where("uid = ?", id).Get(&m); err != nil || has == false {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

// UserisExistByMobile is exist
func UserisExistByMobile(Db *xorm.Engine, n string) (bool, error) {
	has, err := Db.Where("phone = ? and phone<>''", n).Exist(&model.User{})

	if err != nil {
		return false, err
	}
	return has, nil
}
func UserisFindByMobile(sess *xorm.Session, n string) *model.User {
	var data model.User
	has, err := sess.Where("phone = ? and phone<>''", n).Get(&data)

	if err != nil || has == false {
		return nil
	}
	return &data
}

// UserInByUIDByLevel is In查询 以及是否是有效用户
func UserInByUIDByLevel(Db *xorm.Engine, ids []int, levelID interface{}) (*[]model.User, error) {
	var m []model.User
	if err := Db.In("uid", ids).Where("level = ?", levelID).
		Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

// UserFindByMobile search user by mobile
func UserFindByMobile(Db *xorm.Engine, mobile string) (*model.User, error) {
	var m model.User
	if has, err := Db.Where("(phone = ? OR uid = ?) AND delete_at = 0", mobile, mobile).
		Get(&m); err != nil || has == false {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

// UserFindExistByMobile search user by mobile
func UserFindExistByMobile(Db *xorm.Engine, mobile string) (*model.User, bool, error) {
	var m model.User
	has, err := Db.Where("(phone = ? OR uid = ?) AND delete_at = 0", mobile, mobile).Get(&m)
	if err != nil {
		logx.Infof("UserFindExistByMobile err")
		return nil, false, logx.Warn(err)
	}
	return &m, has, nil
}

// UserFindByMobile search user by mobile
func UserFindByMobileAll(Db *xorm.Engine, mobile string) (*model.User, error) {
	var m model.User
	if has, err := Db.Where("(phone = ? OR uid = ?)", mobile, mobile).
		Get(&m); err != nil || has == false {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

// UserGetByMobileIgnoreDelete search user by mobile ignore delete
func UserGetByMobileIgnoreDelete(Db *xorm.Engine, mobile, zone string) (*model.User, bool, error) {
	m := new(model.User)
	sess := Db.Where("phone = ?", mobile)
	if zone != "" && zone != "86" {
		sess = sess.And("zone=?", zone)
	}
	has, err := sess.Get(m)
	if err != nil {
		return nil, false, logx.Warn(err)
	}
	return m, has, nil
}

// UsersFindByMobileLike search users by mobile
func UsersFindByMobileLike(Db *xorm.Engine, mobile string) (*[]model.User, error) {
	var m []model.User
	if err := Db.Where("phone like ?", "%"+mobile+"%").
		Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

// UsersFindByNickNameLike search users by nickname
func UsersFindByNickNameLike(Db *xorm.Engine, nickname string) (*[]model.User, error) {
	var m []model.User
	if err := Db.Where("nickname like ?", "%"+nickname+"%").
		Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}
func UsersFindByInviteCode(Db *xorm.Engine, nickname string) (*[]model.UserProfile, error) {
	var m []model.UserProfile
	if err := Db.Where("invite_code like ? or custom_invite_code like ?", "%"+strings.ToLower(nickname)+"%", "%"+strings.ToLower(nickname)+"%").
		Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}
func UsersFindByInviteCodeMust(Db *xorm.Engine, nickname string) (*[]model.UserProfile, error) {
	var m []model.UserProfile
	if err := Db.Where("invite_code = ? or custom_invite_code = ?", strings.ToLower(nickname), strings.ToLower(nickname)).
		Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

// UsersInByIds is 根据ids 查找users
func UsersInByIds(Db *xorm.Engine, ids []int, limit, start int) (*[]model.User, error) {
	var m []model.User
	if limit == 0 && start == 0 {
		if err := Db.In("uid", ids).
			Find(&m); err != nil {
			return nil, logx.Warn(err)
		}
		return &m, nil
	}
	if err := Db.In("uid", ids).Limit(limit, start).
		Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

// UsersInByIdsWhereLv is 根据ids和 lv会员等级 查找users
func UsersInByIdsWhereLv(Db *xorm.Engine, ids []int, lv interface{}, limit, start int) (*[]model.User, error) {
	var m []model.User
	if limit == 0 && start == 0 {
		if err := Db.Where("level = ?", lv).In("uid", ids).
			Find(&m); err != nil {
			return nil, logx.Warn(err)
		}
		return &m, nil
	}
	if err := Db.Where("level = ?", lv).In("uid", ids).Limit(limit, start).
		Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

// UsersInByIdsByAscWhereLv is 根据ids和 lv会员等级 查找users 升排序
func UsersInByIdsByAscWhereLv(Db *xorm.Engine, ids []int, lv interface{}, limit, start int, c string) (*[]model.User, error) {
	var m []model.User
	if limit == 0 && start == 0 {
		if err := Db.Where("level = ?", lv).In("uid", ids).Asc(c).
			Find(&m); err != nil {
			return nil, logx.Warn(err)
		}
		return &m, nil
	}
	if err := Db.Where("level = ?", lv).In("uid", ids).Asc(c).Limit(limit, start).
		Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

// UsersInByIdsByDescWhereLv is 根据ids和 lv会员等级 查找users 降排序
func UsersInByIdsByDescWhereLv(Db *xorm.Engine, ids []int, lv interface{}, limit, start int, c string) (*[]model.User, error) {
	var m []model.User
	if limit == 0 && start == 0 {
		if err := Db.Where("level = ?", lv).In("uid", ids).Desc(c).
			Find(&m); err != nil {
			return nil, logx.Warn(err)
		}
		return &m, nil
	}
	if err := Db.Where("level = ?", lv).In("uid", ids).Desc(c).Limit(limit, start).
		Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}
func UserFindByPhoneOrUsername(Db *xorm.Engine, mobile string) (*model.User, error) {
	var m model.User
	if has, err := Db.Where("(phone = ? or username=?) AND delete_at = 0", mobile, mobile).
		Get(&m); err != nil || has == false {
		return nil, err
	}
	return &m, nil
}

// UserFindByArkidUserName search user by mobile
func UserFindByArkidUserName(Db *xorm.Engine, name string) (*model.User, error) {
	var m model.User
	if has, err := Db.Where("username = ?", name).
		Get(&m); err != nil || has == false {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

// UserFindByID is find user byid
func UserFindByID(Db *xorm.Engine, id interface{}) (*model.User, error) {
	var m model.User
	if has, err := Db.Where("uid = ?", id).
		Get(&m); err != nil || has == false {
		return nil, logx.Warn(err)
	}
	return &m, nil
}
func UserFindByIDWithSession(sess *xorm.Session, id interface{}) (*model.User, error) {
	var m model.User
	if has, err := sess.Where("uid = ?", id).
		Get(&m); err != nil || has == false {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

func UserFindByIDs(Db *xorm.Engine, uids []int) (*[]model.User, error) {
	var m []model.User
	if err := Db.In("uid", uids).Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

func UserFindByall(Db *xorm.Engine) (*[]model.User, error) {
	var m []model.User
	if err := Db.Where("uid>0").Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}
func UserFindByIDsToStr(Db *xorm.Engine, uids []string) (*[]model.User, error) {
	var m []model.User
	if err := Db.In("uid", uids).Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}
func UserFindByIsSet(Db *xorm.Engine, limit, start int) ([]model.UserProfile, error) {
	var m []model.UserProfile
	if err := Db.Where("is_set=? and parent_uid=0 and uid>0", 0).Limit(limit, start).Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return m, nil
}
func UserFindByParentUid(Db *xorm.Engine, parentUid int) ([]model.UserProfile, error) {
	var m []model.UserProfile
	if err := Db.Where("parent_uid=?", parentUid).Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return m, nil
}

// UsersInByIdsByDesc is 根据某列 降序
func UsersInByIdsByDesc(Db *xorm.Engine, ids []int, limit, start int, c string) (*[]model.User, error) {
	var m []model.User
	if limit == 0 && start == 0 {
		if err := Db.In("uid", ids).Desc(c).
			Find(&m); err != nil {
			return nil, logx.Warn(err)
		}
		return &m, nil
	}
	if err := Db.In("uid", ids).Desc(c).Limit(limit, start).
		Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

// UsersInByIdsByAsc is 根据某列 升序
func UsersInByIdsByAsc(Db *xorm.Engine, ids []int, limit, start int, c string) (*[]model.User, error) {
	var m []model.User
	if limit == 0 && start == 0 {
		if err := Db.In("uid", ids).Asc(c).
			Find(&m); err != nil {
			return nil, logx.Warn(err)
		}
		return &m, nil
	}
	if err := Db.In("uid", ids).Asc(c).Limit(limit, start).
		Find(&m); err != nil {
		return nil, logx.Warn(err)
	}
	return &m, nil
}

// UserInsert is insert user
func UserInsert(Db *xorm.Engine, user *model.User) (int64, error) {
	affected, err := Db.Insert(user)
	if err != nil {
		return 0, err
	}
	return affected, nil
}

// UserIsExistByMobile is mobile exist
func UserIsExistByMobile(Db *xorm.Engine, mobile string) (bool, error) {
	//fmt.Println(mobile)
	has, err := Db.Where("phone = ? OR uid = ?", mobile, mobile).Exist(&model.User{})
	fmt.Println(has, mobile)
	if err != nil {
		return false, err
	}
	return has, nil
}

// UserIsExistByID is mobile exist by id
func UserIsExistByID(Db *xorm.Engine, id string) (bool, error) {
	has, err := Db.Where("uid = ?", id).Exist(&model.User{})
	if err != nil {
		return false, err
	}
	return has, nil
}

// UserUpdate is update user
func UserUpdate(Db *xorm.Engine, uid interface{}, user *model.User, forceColums ...string) (int64, error) {
	var (
		affected int64
		err      error
	)
	if forceColums != nil {
		affected, err = Db.Where("uid=?", uid).Cols(forceColums...).Update(user)
	} else {
		affected, err = Db.Where("uid=?", uid).Update(user)
	}
	if err != nil {
		return 0, err
	}
	return affected, nil
}

func UserUpdateWithSession(Db *xorm.Session, uid interface{}, user *model.User, forceColums ...string) (int64, error) {
	var (
		affected int64
		err      error
	)
	if forceColums != nil {
		affected, err = Db.Where("uid=?", uid).Cols(forceColums...).Update(user)
	} else {
		affected, err = Db.Where("uid=?", uid).Update(user)
	}
	if err != nil {
		return 0, err
	}
	return affected, nil
}

func UpdateUserFinValid() {

}

// UserDelete is delete user
func UserDelete(Db *xorm.Engine, uid interface{}) (int64, error) {
	return Db.Where("uid = ?", uid).Delete(model.User{})
}
func UserFindByPhoneOrNickname(Db *xorm.Engine, mobile string) (*model.User, error) {
	var m model.User
	if has, err := Db.Where("(phone = ? or nickname=?) AND delete_at = 0", mobile, mobile).
		Get(&m); err != nil || has == false {
		return nil, err
	}
	return &m, nil
}
func UserDeleteWithSess(sess *xorm.Session, uid interface{}) (int64, error) {
	return sess.Where("uid = ?", uid).Delete(model.User{})
}

func UserProfileCheckInviteCode(eg *xorm.Engine, uid int, inviteCode string) bool {
	var data model.UserProfile
	get, err := eg.Where("invite_code=? or custom_invite_code=?", inviteCode, inviteCode).Get(&data)
	if get == false || err != nil {
		return false
	}
	if uid == data.Uid {
		return false
	}
	return true
}

func GetUserList(eg *xorm.Engine, arg md.Store, uid int) (*[]md.StoreGroup, int64) {
	var data []md.StoreGroup
	sess := eg.Table("user").Where("user.is_marketer=? and community_team_store.parent_uid=?", 1, uid)
	size := utils.StrToInt(arg.Size)
	start := (utils.StrToInt(arg.P) - 1) * size
	if arg.Name != "" {
		sess.And("community_team_store.name like ?", "%"+arg.Name+"%")
	}
	sess.Join("LEFT", "community_team_store", "user.uid = community_team_store.uid")
	count, err := sess.Limit(size, start).Desc("user.create_at").FindAndCount(&data)
	if err != nil {
		return nil, count
	}
	return &data, count
}
