package system

import (
	"errors"
	"spaceofcheng/services/models"
	"spaceofcheng/services/models/model"
	"spaceofcheng/services/utils"
	"strconv"
	"strings"
	"time"

	"github.com/go-xorm/builder"
	"github.com/go-xorm/xorm"
	"github.com/yl10/kit/encrypt"
)

// UserDAO 当前数据库操作对象
type UserDAO struct {
	ctx *utils.Context
	db  *xorm.Session
}

// NewUserDAO New Inst
func NewUserDAO(ctx *utils.Context) *UserDAO {
	return &UserDAO{
		ctx: ctx,
		db:  ctx.DB,
	}
}

type UserListInfo struct {
	model.SysUser `xorm:"extends"`
	UserTypeNames string
}

// GetUserList 用户列表
func (m *UserDAO) GetUserList(username, typeid, caseids string, page int, pageSize int) ([]UserListInfo, error) {
	var users []UserListInfo
	sql := `select user.*,c.user_type_names from sys_user user left join (
		select a.user_id,GROUP_CONCAT(b.type_name) as user_type_names from sys_user_type a
		INNER join td_user_type b on a.type_id = b.type_id
		group by a.user_id) c on user.user_id = c.user_id where 
		(status> ` + strconv.Itoa(models.STATUS_DEL) + ` and user_name like '%` + username + `%' and user.user_id in 
		(select user_id from sys_user_case where case_id in ('` + strings.Replace(caseids, ",", "','", -1) + `')))`

	if typeid != "" {
		sql = sql + " and user.user_id in (select user_id from sys_user_type where type_id = '" + typeid + "')"
	}

	sql = sql + " order by create_date desc limit " + strconv.Itoa((page-1)*pageSize) + ", " + strconv.Itoa(page*pageSize)
	err := m.db.Sql(sql).Find(&users)
	return users, err
}

// GetUserCount 用户列表count
func (m *UserDAO) GetUserCount(username, typeid, caseids string) (int, error) {
	var users []UserListInfo
	sql := `select user.*,c.user_type_names from sys_user user left join (
		select a.user_id,GROUP_CONCAT(b.type_name) as user_type_names from sys_user_type a
		INNER join td_user_type b on a.type_id = b.type_id
		group by a.user_id) c on user.user_id = c.user_id where 
		(status> ` + strconv.Itoa(models.STATUS_DEL) + ` and user_name like '%` + username + `%' and user.user_id in 
		(select user_id from sys_user_case where case_id in ('` + strings.Replace(caseids, ",", "','", -1) + `')))`

	if typeid != "" {
		sql = sql + " and user.user_id in (select user_id from sys_user_type where type_id = '" + typeid + "')"
	}

	err := m.db.Sql(sql).Find(&users)
	if err != nil {
		return 0, err
	}
	return len(users), nil
}

// UserInfo 用户详情
type UserInfo struct {
	model.SysUser `xorm:"extends"`
	UserType      []model.TdUserType
	UserTag       []model.SysTag
	UserCase      []model.SysUserCase
	UserRole      []model.SysRole
	UserMenu      []model.SysMenu
}

// SysUserForm 映射用户
type SysUserForm struct {
	model.SysUser `xorm:"extends"`
	TypeId        string
	TagIds        string
	BelongCaseId  string
}

// GetUserByID 根据ID获取用户信息
func (m *UserDAO) GetUserByID(userid string) (*UserInfo, error) {
	var userinfo []UserInfo
	sql := `select * from sys_user where user_id='` + userid + `' and status>` + strconv.Itoa(models.STATUS_DEL)
	err := m.db.Sql(sql).Find(&userinfo)
	if err != nil {
		return nil, err
	}
	if len(userinfo) > 0 {
		return &userinfo[0], nil
	}
	return nil, nil
}

// GetUserTypes 获取所有的用户类型
func (m *UserDAO) GetUserTypes(orgid string) ([]model.TdUserType, error) {
	var usertype []model.TdUserType
	err := m.db.Where("status>"+strconv.Itoa(models.STATUS_DEL)).And("org_id=?", orgid).Find(&usertype)
	return usertype, err
}

// GetUserType 获取用户类型
func (m *UserDAO) GetUserType(userid string) ([]model.TdUserType, error) {
	var usertype []model.TdUserType
	err := m.db.In("type_id", builder.Select("type_id").From("sys_user_type").Where(builder.Eq{"user_id": userid}).And(builder.Gt{"status": models.STATUS_DEL})).Find(&usertype)
	return usertype, err
}

// GetUserTag 获取用户标签
func (m *UserDAO) GetUserTag(userid string) ([]model.SysTag, error) {
	var userTag []model.SysTag
	err := m.db.In("tag_id", builder.Select("tag_id").From("sys_user_tag").Where(builder.Eq{"user_id": userid}).And(builder.Gt{"status": models.STATUS_DEL})).Find(&userTag)
	return userTag, err
}

// GetUserCase 获取用户案场
func (m *UserDAO) GetUserCase(userid string) ([]model.SysUserCase, error) {
	var userCase []model.SysUserCase
	// err := m.db.Where("user_id=?", userid).And("status>" + strconv.Itoa(models.STATUS_DEL)).Find(&userCase)
	err := m.db.In("case_id", builder.Select("case_id").From("sys_user_case").Where(builder.Eq{"user_id": userid}).And(builder.Gt{"status": models.STATUS_DEL})).Find(&userCase)
	return userCase, err
}

// GetUserRole 获取用户角色
func (m *UserDAO) GetUserRole(userid string) ([]model.SysRole, error) {
	var userRole []model.SysRole
	err := m.db.In("role_id", builder.Select("role_id").From("sys_user_role").Where(builder.Eq{"user_id": userid}).And(builder.Gt{"status": models.STATUS_DEL})).Find(&userRole)
	return userRole, err
}

// GetUserMenu 获取用户菜单
func (m *UserDAO) GetUserMenu(userid string) ([]model.SysMenu, error) {
	var userMenu []model.SysMenu
	err := m.db.In("menu_id", builder.Select("menu_id").From("sys_user_menu").Where(builder.Eq{"user_id": userid}).And(builder.Gt{"status": models.STATUS_DEL})).Find(&userMenu)
	return userMenu, err
}

// AddUser 新增用户
func (m *UserDAO) AddUser(user model.SysUser) (*model.SysUser, error) {
	user.UserId = utils.GetGUID()
	user.CreateDate = time.Now()
	user.Pwd = encrypt.Md5(encrypt.Md5("123456"), user.UserId)
	user.Status = models.STATUS_NORMAL
	_, err := m.db.Insert(user)
	return &user, err
}

// UpdateUser 修改用户
func (m *UserDAO) UpdateUser(user model.SysUser) error {
	var col = []string{
		"user_name",
		"real_name",
		"sex",
		"work_no",
		"email",
		"phone",
		"headimgurl",
		"user_type_name",
		"case_id",
	}
	_, err := m.db.Cols(col...).Where("user_id=?", user.UserId).Update(user)
	return err
}

// DelUser 删除用户
func (m *UserDAO) DelUser(userid string) error {
	var user = model.SysUser{}
	user.Status = models.STATUS_DEL
	user.UserId = userid
	var cols = []string{
		"status",
	}
	_, err := m.db.Cols(cols...).Where("user_id=?", userid).Update(user)
	return err
}

// DelUserType 删除用户对应的类型信息
func (m *UserDAO) DelUserType(userid string) error {
	sql := "delete from sys_user_type where user_id='" + userid + "'"
	_, err := m.db.Exec(sql)
	return err
}

// SaveUserType 保存用户对应类型信息
func (m *UserDAO) SaveUserType(userid, typeids string) error {
	sql := `insert into sys_user_type(user_id,type_id) select '` + userid + `', type_id from td_user_type where type_id in ('` + strings.Replace(typeids, ",", "','", -1) + `') and status>` + strconv.Itoa(models.STATUS_DEL)
	_, err := m.db.Exec(sql)
	return err
}

// DelUserRole 删除用户对应的角色信息
func (m *UserDAO) DelUserRole(userid string) error {
	sql := "delete from sys_user_role where user_id='" + userid + "'"
	_, err := m.db.Exec(sql)
	return err
}

// SaveUserRole 保存用户对应角色信息
func (m *UserDAO) SaveUserRole(userid, roleids string) error {
	sql := `insert into sys_user_role(user_id,role_id) select '` + userid + `', role_id from sys_role where role_id in ('` + strings.Replace(roleids, ",", "','", -1) + `') and status>` + strconv.Itoa(models.STATUS_DEL)
	_, err := m.db.Exec(sql)
	return err
}

// GetUserByRole 根据角色获取用户信息
func (m *UserDAO) GetUserByRole(roleid string) ([]model.SysUserRole, error) {
	var userroles []model.SysUserRole
	err := m.db.Where("role_id=?", roleid).Find(&userroles)
	return userroles, err
}

// DelUserMenu 删除用户对应的菜单信息
func (m *UserDAO) DelUserMenu(userid string) error {
	sql := "delete from sys_user_menu where user_id='" + userid + "'"
	_, err := m.db.Exec(sql)
	return err
}

// SaveUserMenu 保存用户对应的菜单信息
func (m *UserDAO) SaveUserMenu(userid string) error {
	sql := `insert into sys_user_menu(user_id,menu_id) select '` + userid + `', a.menu_id from sys_role_menu a inner join sys_user_role b on a.role_id = b.role_id inner join sys_menu c on c.menu_id = a.menu_id where b.user_id = '` + userid + `' and c.status>` + strconv.Itoa(models.STATUS_DEL)
	_, err := m.db.Exec(sql)
	return err
}

// DelUserTag 删除用户对应的标签信息
func (m *UserDAO) DelUserTag(userid string) error {
	sql := "delete from sys_user_tag where user_id='" + userid + "'"
	_, err := m.db.Exec(sql)
	return err
}

// SaveUserTag 保存用户对应标签信息
func (m *UserDAO) SaveUserTag(userid, tagids string) error {
	sql := `insert into sys_user_tag(user_id,tag_id) select '` + userid + `', tag_id from sys_tag where tag_id in ('` + strings.Replace(tagids, ",", "','", -1) + `') and status>` + strconv.Itoa(models.STATUS_DEL)
	_, err := m.db.Exec(sql)
	return err
}

// DelUserBelongCase 删除用户的所属案场
func (m *UserDAO) DelUserBelongCase(userid string) error {
	sql := "delete from sys_user_case where is_belong=1 and user_id='" + userid + "'"
	_, err := m.db.Exec(sql)
	return err
}

// DelUserCase 删除用户的案场信息
func (m *UserDAO) DelUserCase(userid string) error {
	sql := "delete from sys_user_case where is_belong=0 and is_created=0 and user_id='" + userid + "'"
	_, err := m.db.Exec(sql)
	return err
}

// SaveUserCase 保存用户对应案场信息
func (m *UserDAO) SaveUserCase(usercase model.SysUserCase) error {
	usercase.CreateDate = time.Now()
	usercase.Status = models.STATUS_NORMAL
	_, err := m.db.Insert(usercase)
	return err
}

// SaveUserCaseByUserTag 根据用户标签保存用户对应案场
func (m *UserDAO) SaveUserCaseByUserTag(userid string) error {
	sql := `insert into sys_user_case(user_id, case_id, case_name, is_belong, status, create_date) 
	select c.user_id, a.case_id,a.case_name, 0,?,now() from sys_case a 
	inner join sys_tag_case b on a.case_id = b.case_id
	inner join sys_user_tag c on b.tag_id = c.tag_id
	where c.user_id = ? and a.status > ` + strconv.Itoa(models.STATUS_DEL)

	_, err := m.db.Exec(sql, userid, models.STATUS_DEL)
	return err
}

// ValidatePassword 验证密码是否正确
func (m *UserDAO) ValidatePassword(user *model.SysUser, password string) bool {
	return user.Pwd == encrypt.Md5(password, user.UserId)
}

// UpdatePassword 更新用户密码
func (m *UserDAO) UpdatePassword(userID, newPass string) error {
	password := encrypt.Md5(newPass, userID)

	sql := "update sys_user set pwd=? where user_id=?"

	_, err := m.db.Exec(sql, password, userID)
	if err != nil {
		return err
	}

	return nil
}

// SaveUserMapping 保存用户映射信息
func (m *UserDAO) SaveUserMapping(usermapping *model.TaUserMapping) error {
	usermapping.MappingId = utils.GetGUID()
	_, err := m.db.Insert(usermapping)
	return err
}

// UpdateUserHeadImg 修改用户头像
func (m *UserDAO) UpdateUserHeadImg(userid, imgurl string) error {
	var col = []string{
		"headimgurl",
	}
	_, err := m.db.Cols(col...).Where("user_id=?", userid).Update(model.SysUser{
		Headimgurl: imgurl,
	})
	return err
}

// UpdateCustomerHeadImg 更新会员头像
func (m *UserDAO) UpdateCustomerHeadImg(customerid, username, imgurl string) error {
	var col = []string{
		"headimgurl",
	}
	_, err := m.db.Cols(col...).Where("customer_id=?", customerid).Update(model.TaCustomer{
		Headimgurl: imgurl,
	})
	return err
}

// GetUserCustomer 获取我的推荐客户
func (m *UserDAO) GetUserCustomer(userid string, page int, pageSize int) ([]model.TaCustomer, error) {
	var customers []model.TaCustomer
	err := m.db.Where("status>"+strconv.Itoa(models.STATUS_DEL)).And("recommend_id=?", userid).Limit(pageSize, (page-1)*pageSize).Desc("create_date").Find(&customers)
	return customers, err
}

// GetUserByName 依据账户获取人员信息
func (m *UserDAO) GetUserByName(userName string) (*model.SysUser, error) {
	user := model.SysUser{}

	has, err := m.db.Where("user_name=?", userName).Get(&user)
	if err != nil {
		return nil, err
	}

	if !has {
		return nil, nil
	}

	return &user, nil
}

// GetUserByPhone 依据手机号获取人员信息
func (m *UserDAO) GetUserByPhone(phone string) (*model.SysUser, error) {
	user := model.SysUser{}

	has, err := m.db.Where("phone=?", phone).Get(&user)
	if err != nil {
		return nil, err
	}

	if !has {
		return nil, nil
	}

	return &user, nil
}

// UpdateUserMapping 更新用户映射
func (m *UserDAO) UpdateUserMapping(userMap *model.TaUserMapping, cols []string) error {
	if userMap.MappingId == "" {
		return errors.New("用户映射信息不存在")
	}

	_, err := m.db.Where("mapping_id=?", userMap.MappingId).Cols(cols...).Update(userMap)
	return err
}

type UserWithType struct {
	model.SysUser
	TypeId   string
	TypeName string
	CaseId   string
}

// GetUserWithTypeByID 获取用户类型
func (m *UserDAO) GetUserWithTypeByID(userID string) ([]UserWithType, error) {
	query := `
		SELECT
			t.*, m.type_id,
			m.type_name,
			m.case_id
		FROM
			sys_user t
		JOIN sys_user_type s ON t.user_id = s.user_id
		JOIN td_user_type m ON s.type_id = m.type_id
		AND m.status = ?
		WHERE
			t.user_id = ?
	`

	var userTypes []UserWithType
	if err := m.db.SQL(query, models.STATUS_NORMAL, userID).Find(&userTypes); err != nil {
		return nil, err
	}

	return userTypes, nil
}

// GetForbidUserByUserID 查询禁用人员
func (m *UserDAO) GetForbidUserByUserID(userID string) ([]model.TaForbidUser, error) {
	var fbUsers []model.TaForbidUser

	if err := m.db.Where("user_id=?", userID).Find(&fbUsers); err != nil {
		return nil, err
	}

	return fbUsers, nil
}
