package models

import (
	"LAPP_LF_MOM_BACKEND/db"
	"LAPP_LF_MOM_BACKEND/utils"
	"errors"
	"golang.org/x/crypto/bcrypt"
	"strings"
	"xorm.io/core"
)

/***
*CreateBy:lou
*Date:2020/5/15
*TableName:用户表
**********/
// User
type User struct {
	// key
	IdentityKey string
	// 用户名
	UserName  string
	FirstName string
	LastName  string
	// 角色
	Role string
}

type Usertab struct {
	Pid            int    `xorm:"not null pk comment('工厂ID') INT(0)" form:"pid" json:"pid"`
	Userid         string `xorm:"not null pk comment('用户ID') VARCHAR(40)" form:"userid" json:"userid"`
	Name           string `xorm:"comment('用户名') VARCHAR(40)" form:"name" json:"name"`
	Password       string `xorm:"comment('密码') VARCHAR(255)" form:"password" json:"password"`
	Nickname       string `xorm:"comment('用户昵称') VARCHAR(40)" form:"nickname" json:"nickname"`
	Depid          int    `xorm:"comment('归属部门') int(11)" form:"depid" json:"depid"`
	Phone          string `xorm:"comment('手机号') VARCHAR(20)" form:"phone" json:"phone"`
	Avatar         string `xorm:"comment('用户头像') VARCHAR(128)" form:"avatar" json:"avatar"`
	Email          string `xorm:"comment('邮箱') VARCHAR(40)" form:"email" json:"email"`
	Status         string `xorm:"comment('状态') VARCHAR(1)" form:"status" json:"status"`
	Gender         string `xorm:"comment('性别') VARCHAR(1)" form:"gender" json:"gender"`
	Position       string `xorm:"comment('岗位') VARCHAR(40)" form:"position" json:"position"`
	Role           string `xorm:"comment('用户角色') VARCHAR(40)" form:"role" json:"role"`
	RoleId         int    `xorm:"comment('角色编码') int(11)" json:"role_id"` // 角色编码
	Remark         string `xorm:"comment('备注') VARCHAR(100)" form:"remark" json:"remark"`
	Createtime     string `xorm:"comment('创建时间') VARCHAR(14)" form:"createtime" json:"createtime"`
	Lastmodifytime string `xorm:"comment('最近一次更新时间') VARCHAR(14)" form:"lastmodifytime" json:"lastmodifytime"`
	Lastmodify     string `xorm:"comment('最近一次更新人员') VARCHAR(40)" form:"lastmodify" json:"lastmodify"`
}

func (t *Usertab) TableName() string {
	return "usertab"
}

type UserPage struct {
	Usertab  `xorm:"extends"`
	DeptName string `xorm:"-" json:"deptName"`
}

type SysUserView struct {
	Usertab `xorm:"extends"`
	Roletab `xorm:"extends"`
}

type UserViewInfo struct {
	Pid      int    `json:"pid"`
	Password string `json:"password"`
	Userid   string `json:"userid"`
	Name     string `json:"name"`
	Nickname string `json:"nickname"`
	Phone    string `json:"phone"`
	Email    string `json:"email"`
	Status   string `json:"status"`
	Gender   string `json:"gender"`
	RoleId   int    `json:"role_id"`
	RoleKey  string `json:"role_key"`
	Rolename string `json:"rolename"`
	Remark   string `json:"remark"`
}

// 清除string字段的右侧空格
func (t *Usertab) Clipped() {
	utils.TrimStruct(t, *t)
}

// 获取用户数据
func (t *Usertab) Get() (UserView UserViewInfo, err error) {
	e := db.Eloquent.Master()

	var user SysUserView
	table := e.Table(t.TableName()).Select("usertab.*, roletab.rolename").Where("1=1")
	table = table.Join("LEFT", "roletab", "usertab.role_id=roletab.role_id")
	if t.Userid != "" {
		table = table.And("userid = ?", t.Userid)
	}
	if t.Pid != 0 {
		table = table.And("pid = ?", t.Pid)
	}
	if t.Name != "" {
		table = table.And("name = ?", t.Name)
	}

	if t.RoleId != 0 {
		table = table.And("role_id = ?", t.RoleId)
	}

	if _, err = table.Get(&user); err != nil {
		return
	}
	user.Usertab.Clipped()
	user.Roletab.Clipped()
	UserView.Password = user.Usertab.Password
	UserView.Userid = user.Usertab.Userid
	UserView.Pid = user.Usertab.Pid
	UserView.Phone = user.Usertab.Phone
	UserView.Rolename = user.Roletab.Rolename
	UserView.RoleId = user.Usertab.RoleId
	UserView.Status = user.Usertab.Status
	UserView.Nickname = user.Usertab.Nickname
	UserView.Name = user.Usertab.Name
	UserView.Email = user.Usertab.Email

	return
}

func (t *Usertab) CreateUser(user ...*Usertab) (int64, error) {
	e := db.Eloquent.Master()
	return e.Insert(user)
}

func (t *Usertab) GetUserByUsername() (bool, error) {
	e := db.Eloquent.Master()
	return e.Get(t)
}

type SysUserPwd struct {
	OldPassword string `json:"oldPassword"`
	NewPassword string `json:"newPassword"`
}

func (t *Usertab) SetPwd(pwd *SysUserPwd) (Result bool, err error) {
	e := db.Eloquent.Master()
	user, _ := t.Get()
	_, err = utils.CompareHashAndPassword(user.Password, pwd.OldPassword)
	if err != nil {
		if strings.Contains(err.Error(), "hashedPassword is not the hash of the given password") {
		}
		return
	}
	t.Password = pwd.NewPassword
	var upuser Usertab
	upuser.Password =pwd.NewPassword
	err = upuser.Encrypt()
	if err != nil{
		return
	}
	_, err = e.ID(core.PK{t.Pid,t.Userid}).Update(&upuser)
	if err != nil {
		return false, err
	}
	return
}

func (t *Usertab) GetPage(pageSize int, pageIndex int) ([]Usertab, int, error) {
	doc := make([]Usertab, 0)
	e := db.Eloquent.Master()
	query := e.Where("1=1")
	where := "where 1=1 "
	if !utils.ValueIsEmpty(t.Userid) {
		query = query.And("userid = ?", t.Userid)
		where += " and userid = " + "'" + t.Userid + "'"
	}
	if !utils.ValueIsEmpty(t.Phone) {
		search := "%" + t.Phone + "%"
		query = query.And("phone like ?", search)
		where += " and phone like " + "'%" + t.Phone + "%'"
	}
	if !utils.ValueIsEmpty(t.Name) {
		searchName := "%" + t.Name + "%"
		query = query.And("name like ?", searchName)
		where += " and name like " + "'%" + t.Name + "%'"
	}
	Offset := (pageIndex - 1) * pageSize
	err := e.SQL("SELECT TOP " + utils.ValueToString(pageSize, "") + " usertab.* FROM usertab " + where + " AND (convert(varchar(10),pid)+convert(varchar(40),userid) NOT IN (SELECT TOP " + utils.ValueToString(Offset, "") + " convert(varchar(10),pid)+convert(varchar(40),userid) FROM usertab " + where + " ORDER BY createtime DESC)) ORDER BY createtime DESC").Find(&doc)
	if err != nil {
		return nil, 0, err
	}
	for k, _ := range doc {
		doc[k].Password = ""
		doc[k].Clipped()
	}

	usercount := new(Usertab)

	count, _ := query.Count(usercount)
	return doc, int(count), nil
}

//加密
func (t *Usertab) Encrypt() (err error) {
	if t.Password == "" {
		return
	}

	var hash []byte
	if hash, err = bcrypt.GenerateFromPassword([]byte(t.Password), bcrypt.DefaultCost); err != nil {
		return
	} else {
		t.Password = string(hash)
		return
	}
}

//添加
func (t *Usertab) Insert() (id int, err error) {
	if err = t.Encrypt(); err != nil {
		return
	}
	e := db.Eloquent.Master()
	// check 用户名
	usercount := new(Usertab)
	count, err := e.Table(t.TableName()).Where("userid = ?", t.Userid).Count(usercount)
	if count > 0 {
		err = errors.New("账户已存在！")
		return
	}
	var inid int64
	//添加数据
	if inid, err = e.Table(t.TableName()).Insert(t); err != nil {
		return
	}
	id = int(inid)
	return
}

//修改
func (t *Usertab) Update(id string) (update Usertab, err error) {
	if err = t.Encrypt(); err != nil {
		return
	}
	e := db.Eloquent.Master()
	if _, err = e.Table(t.TableName()).Where("userid=?",id).Get(&update); err != nil {
		return
	}
	if t.RoleId == 0 {
		t.RoleId = update.RoleId
	}
	update.Clipped()
	//参数1:是要修改的数据

	var upuser Usertab
	upuser.Phone =t.Phone
	upuser.Email =t.Email
	upuser.Remark =t.Remark
	upuser.RoleId =t.RoleId
	upuser.Role = t.Role
	upuser.Avatar = t.Avatar
	upuser.Status = t.Status
	upuser.Nickname = t.Nickname
	upuser.Name = t.Name
	upuser.Lastmodify = t.Lastmodify
	upuser.Lastmodifytime = t.Lastmodifytime

	//参数2:是修改的数据
	if _, err = e.Table(t.TableName()).ID(core.PK{t.Pid,t.Userid}).Update(&upuser); err != nil {
		return
	}
	return
}

func (t *Usertab) BatchDelete(ids []string) (Result bool, err error) {
	e := db.Eloquent.Master()
	idstr := utils.IDsToStrings(ids)
	if _, err = e.Table(t.TableName()).Where("userid in ("+idstr+")").Delete(&Usertab{}); err != nil {
		return
	}
	Result = true
	return
}
