package ldap_lib

import (
	"encoding/hex"
	"errors"
	"github.com/go-ldap/ldap/v3"
	"strconv"
	"strings"
)

type LdapUserInfo struct {
	UserId             int64    `json:"userId"`
	UserDN             string   `json:"user_dn"`
	UserName           string   `json:"user_name"`            //用户名
	Password           string   `json:"password"`             //密码
	Email              string   `json:"email"`                //邮箱
	Mobile             string   `json:"mobile"`               //手机号
	Avatar             string   `json:"avatar"`               //头像地址
	EmployeeType       int64    `json:"employee_type"`        //1正式 2实习 3外包
	GroupId            int64    `json:"group_id"`             //权限组id
	OrganizationDNList []string `json:"organization_dn_list"` //加入的部门
	Status             int64    `json:"status,options=0|1"`   //状态 1正常0离职
}

// 获取用户详情
func (l *Ldap) GetLdapUserInfo(userDN string) (*LdapUserInfo, error) {
	res, err := l.Search(userDN, ldap.ScopeWholeSubtree, "(&(objectClass=posixAccount)(objectClass=inetOrgPerson))", nil, nil)
	if err != nil {
		return nil, err
	}
	if len(res.Entries) != 1 {
		return nil, errors.New("查询到不到用户信息")
	}
	if len(res.Entries) == 0 {
		return nil, errors.New("ldap user not exists(entry not exists)")
	}
	userEntry := res.Entries[0]
	if userEntry.DN != userDN {
		return nil, errors.New("ldap user not exists(DN not match)")
	}
	user := &LdapUserInfo{
		UserDN: userEntry.DN,
	}
	for _, attr := range userEntry.Attributes {
		switch attr.Name {
		case "uidNumber": //用户id
			if len(attr.Values) == 0 {
				return nil, errors.New("用户id不存在")
			}
			user.UserId, err = strconv.ParseInt(attr.Values[0], 10, 64)
			if err != nil {
				return nil, err
			}
		case "sn": //用户真名
			user.UserName = strings.Join(attr.Values, "")
		case "mail": //邮箱
			user.Email = strings.Join(attr.Values, "")
		case "mobile": //手机号
			user.Mobile = strings.Join(attr.Values, "")
		case "postalAddress": //头像
			user.Avatar = strings.Join(attr.Values, "")
		case "userPassword": //密码
			user.Password = strings.Join(attr.Values, ",")
		case "employeeType": //员工类型
			if len(attr.Values) == 0 {
				return nil, errors.New("用户类型不存在")
			}
			user.EmployeeType, err = strconv.ParseInt(attr.Values[0], 10, 64)
			if err != nil {
				return nil, err
			}
		case "postalCode": //状态
			if len(attr.Values) == 0 {
				return nil, errors.New("用户状态不存在")
			}
			user.Status, err = strconv.ParseInt(attr.Values[0], 10, 64)
			if err != nil {
				return nil, err
			}
		case "roomNumber": //权限组id
			if len(attr.Values) == 0 {
				return nil, errors.New("权限组id不存在")
			}
			user.GroupId, err = strconv.ParseInt(attr.Values[0], 10, 64)
			if err != nil {
				return nil, err
			}
		case "departmentNumber": //加入的部门dn集合
			user.OrganizationDNList = attr.Values
		}
	}
	if user.UserId == 0 {
		return nil, errors.New("查询到的不是用户信息!!!")
	}
	return user, nil
}

// 获取基础组用户列表
func (l *Ldap) GetLdapBaseTeamUserList(pageSize uint32, filter, pageCookie string) ([]LdapUserInfo, string, error) {
	pageCookieBytes, err := hex.DecodeString(pageCookie)
	if err != nil {
		return nil, "", err
	}
	result, err := l.SearchWithPaging(l.peopleGroupDN, ldap.ScopeWholeSubtree, filter, nil, pageSize, string(pageCookieBytes))
	if err != nil {
		return nil, "", err
	}
	list := make([]LdapUserInfo, 0, pageSize)
	for _, entry := range result.Entries {
		user := LdapUserInfo{
			UserDN: entry.DN,
		}
		for _, attr := range entry.Attributes {
			switch attr.Name {
			case "uidNumber": //用户id
				if len(attr.Values) == 0 {
					return nil, "", errors.New("用户id不存在")
				}
				user.UserId, err = strconv.ParseInt(attr.Values[0], 10, 64)
				if err != nil {
					return nil, "", err
				}
			case "sn": //用户真名
				user.UserName = strings.Join(attr.Values, "")
			case "mail": //邮箱
				user.Email = strings.Join(attr.Values, "")
			case "mobile": //手机号
				user.Mobile = strings.Join(attr.Values, "")
			case "postalAddress": //头像
				user.Avatar = strings.Join(attr.Values, "")
			case "userPassword": //密码
				user.Password = strings.Join(attr.Values, ",")
			case "employeeType": //员工类型
				if len(attr.Values) == 0 {
					return nil, "", errors.New("用户类型不存在")
				}
				user.EmployeeType, err = strconv.ParseInt(attr.Values[0], 10, 64)
				if err != nil {
					return nil, "", err
				}
			case "postalCode": //状态
				if len(attr.Values) == 0 {
					return nil, "", errors.New("用户状态不存在")
				}
				user.Status, err = strconv.ParseInt(attr.Values[0], 10, 64)
				if err != nil {
					return nil, "", err
				}
			case "roomNumber": //权限组id
				if len(attr.Values) == 0 {
					return nil, "", errors.New("权限组id不存在")
				}
				user.GroupId, err = strconv.ParseInt(attr.Values[0], 10, 64)
				if err != nil {
					return nil, "", err
				}
			case "departmentNumber": //加入的部门dn集合
				user.OrganizationDNList = attr.Values
			}
		}
		list = append(list, user)
	}
	rspCookie := ""
	// 检查是否还有更多条目需要获取
	controls := result.Controls
	if len(controls) > 0 {
		cookieControl := controls[0]
		if control, ok := cookieControl.(*ldap.ControlPaging); ok {
			rspCookie = hex.EncodeToString(control.Cookie)
		}
	}
	return list, rspCookie, nil
}

// 从基础用户组中获取指定一批用户
func (l *Ldap) GetLdapBaseTeamUsersByParams(filter string) ([]LdapUserInfo, error) {
	result, err := l.Search(l.peopleGroupDN, ldap.ScopeWholeSubtree, filter, nil, nil)
	if err != nil {
		return nil, err
	}
	list := make([]LdapUserInfo, 0, len(result.Entries))
	for _, entry := range result.Entries {
		user := LdapUserInfo{
			UserDN: entry.DN,
		}
		for _, attr := range entry.Attributes {
			switch attr.Name {
			case "uidNumber": //用户id
				if len(attr.Values) == 0 {
					return nil, errors.New("用户id不存在")
				}
				user.UserId, err = strconv.ParseInt(attr.Values[0], 10, 64)
				if err != nil {
					return nil, err
				}
			case "sn": //用户真名
				user.UserName = strings.Join(attr.Values, "")
			case "mail": //邮箱
				user.Email = strings.Join(attr.Values, "")
			case "mobile": //手机号
				user.Mobile = strings.Join(attr.Values, "")
			case "postalAddress": //头像
				user.Avatar = strings.Join(attr.Values, "")
			case "userPassword": //密码
				user.Password = strings.Join(attr.Values, ",")
			case "employeeType": //员工类型
				if len(attr.Values) == 0 {
					return nil, errors.New("用户类型不存在")
				}
				user.EmployeeType, err = strconv.ParseInt(attr.Values[0], 10, 64)
				if err != nil {
					return nil, err
				}
			case "postalCode": //状态
				if len(attr.Values) == 0 {
					return nil, errors.New("用户状态不存在")
				}
				user.Status, err = strconv.ParseInt(attr.Values[0], 10, 64)
				if err != nil {
					return nil, err
				}
			}
		}
		list = append(list, user)
	}
	return list, nil
}