package logic

import (
	"context"
	"fusenapi/utils/auth"
	"fusenapi/utils/basic"
	"github.com/go-ldap/ldap/v3"
	"log"
	"sort"
	"strings"

	"fusenapi/server/ldap-admin/internal/svc"
	"fusenapi/server/ldap-admin/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetDepartmentsLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetDepartmentsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetDepartmentsLogic {
	return &GetDepartmentsLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// 处理进入前逻辑w,r
// func (l *GetDepartmentsLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
// }
type DNItem struct {
	Attribute map[string]interface{} `json:"attribute"`
	DN        string                 `json:"dn"`
	ParentDN  string                 `json:"parent_dn"`
	Sort      int                    `json:"sort"`
	Child     []*DNItem              `json:"child"`
}

func (l *GetDepartmentsLogic) GetDepartments(req *types.Request, userinfo *auth.UserInfo) (resp *basic.Response) {
	//从ldap获取组织架构数据
	searchRequest := ldap.NewSearchRequest(
		l.svcCtx.Config.Ldap.BaseDN, //这里后续需要修改,不同的人只能查询他的下属列表
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
		"(objectClass=*)", //所有object
		nil,
		nil,
	)
	// 执行搜索请求
	searchResult, err := l.svcCtx.Ldap.Search(searchRequest)
	if err != nil {
		log.Fatal(err)
	}
	mapDN := make(map[string]*DNItem)
	sortNum := 0
	//每个DN存入map
	for _, v := range searchResult.Entries {
		sortNum++
		attribute := make(map[string]interface{})
		for _, attr := range v.Attributes {
			switch attr.Name {
			case "objectClass": //objectcalss属性特别处理
				mapObjectClass := make(map[string]struct{})
				for _, objectClassItem := range attr.Values {
					mapObjectClass[objectClassItem] = struct{}{}
				}
				attribute[attr.Name] = mapObjectClass
			default: //普通属性
				attribute[attr.Name] = strings.Join(attr.Values, ",")
			}
		}
		mapDN[v.DN] = &DNItem{
			DN:        v.DN,
			ParentDN:  "",
			Attribute: attribute,
			Sort:      sortNum,
			Child:     make([]*DNItem, 0, 100),
		}
	}
	//组织树形层级关系
	minLevel := 0
	for dn, v := range mapDN {
		sl := strings.Split(dn, ",")
		lensl := len(sl)
		if lensl < minLevel || minLevel == 0 {
			minLevel = lensl
		}
		//没有父级
		if lensl <= 1 {
			continue
		}
		//有父级
		parentDN := strings.Join(sl[1:], ",")
		if parent, ok := mapDN[parentDN]; ok {
			v.ParentDN = parentDN
			parent.Child = append(parent.Child, v)
			//排序
			sort.Slice(parent.Child, func(i, j int) bool {
				return parent.Child[i].Sort < parent.Child[j].Sort
			})
		}
	}
	//只获取最顶层
	list := make([]interface{}, 0, len(mapDN))
	for dn, v := range mapDN {
		sl := strings.Split(dn, ",")
		if len(sl) == minLevel {
			list = append(list, v)
		}
	}
	return resp.SetStatusWithMessage(basic.CodeOK, "", list)
}