package service

import (
	"context"
	"gadmin/config"
	"gadmin/internal/admin/forms"
	"gadmin/internal/gorm/model"
	"gadmin/internal/gorm/query"
	"gadmin/utility/character"
	"github.com/sirupsen/logrus"
	"os"
	"sort"
	"strings"
)

var Menu = NewAMenu()

type aMenu struct{}

func NewAMenu() *aMenu {
	return &aMenu{}
}

func (s *aMenu) GetMenuList(systemId int32) ([]*forms.Menu, error) {
	q := query.Use(config.AdminDB).AdminMenu
	m := q.WithContext(context.Background())
	m = m.Where(q.Disable.Eq(0), q.SystemID.Eq(systemId)).Order(q.Sort)
	if os.Getenv("ADMIN_IS_LOCAL") != "1" {
		m = m.Where(q.LocalShow.Eq(0))
	}
	menus, err := m.Find()
	if err != nil {
		logrus.Error(err)
		return nil, err
	}
	retMenus := handleMenus(menus)
	return retMenus, nil
}

func handleMenus(menus []*model.AdminMenu) []*forms.Menu {
	menuMap := make(map[int32]*forms.Menu, 0)
	for _, menu := range menus {
		item := &forms.Menu{
			Id:        menu.ID,
			Component: menu.Component,
			Meta: &forms.MenuMeta{
				Icon:       menu.Icon,
				Sort:       menu.Sort,
				Title:      menu.Title,
				Hidden:     menu.Hidden == 1,
				ActiveMenu: menu.ActiveMenu,
				IsRoot:     menu.IsRoot == 1,
				IsSuper:    menu.IsSuper == 1,
			},
			Name:     menu.Name,
			Path:     menu.Path,
			Redirect: menu.Redirect,
			Children: []*forms.Menu{},
		}

		if menu.ParentID == 0 {
			if _, ok := menuMap[menu.ID]; ok {
				menuMap[menu.ID].Id = menu.ID
				menuMap[menu.ID].Component = menu.Component
				menuMap[menu.ID].Meta = item.Meta
				menuMap[menu.ID].Name = menu.Name
				menuMap[menu.ID].Path = menu.Path
				menuMap[menu.ID].Redirect = menu.Redirect
			} else {
				menuMap[menu.ID] = item
			}
		} else {
			if _, ok := menuMap[menu.ParentID]; ok {
				menuMap[menu.ParentID].Children = append(menuMap[menu.ParentID].Children, item)
			} else {
				menuMap[menu.ParentID] = &forms.Menu{
					Id:   menu.ParentID,
					Meta: &forms.MenuMeta{},
					Children: []*forms.Menu{
						item,
					},
				}
			}
		}
	}
	retMenus := make([]*forms.Menu, 0, len(menuMap))
	for _, menu := range menuMap {
		retMenus = append(retMenus, menu)
	}
	sort.Slice(retMenus, func(i, j int) bool {
		return retMenus[i].Meta.Sort < retMenus[j].Meta.Sort
	})
	return retMenus
}

func (s *aMenu) GetRoleMenuList(systemId int32, roleId int64, token string) ([]*forms.Menu, error) {
	//lists := GetMenuList(c)
	lists, err := s.GetMenuList(systemId)
	if err != nil {
		return nil, err
	}
	for _, item := range lists {
		if strings.Contains(item.Name, "{access-token}") {
			item.Name = strings.ReplaceAll(item.Name, "{access-token}", token)
		}
		if len(item.Children) > 0 {
			for _, children := range item.Children {
				if strings.Contains(children.Name, "{access-token}") {
					children.Name = strings.ReplaceAll(children.Name, "{access-token}", token)
				}
			}
		}
	}
	// 获取角色可查看的页面
	// 超管查看所有页面
	if config.IsSuperRole(roleId) {
		return lists, nil
	}
	var rolePages []int32
	rdb := query.Use(config.AdminDB).AdminRoleMenu
	m := rdb.WithContext(context.Background())
	err = m.Where(rdb.RoleID.Eq(int32(roleId)), rdb.SystemID.Eq(systemId)).Pluck(rdb.PageID, &rolePages)
	if err != nil {
		logrus.Error("AdminRole... err:%+v", err)
		return nil, err
	}
	newList := make([]*forms.Menu, 0)
	//if len(rolePages) == 0 { // 没有配置权限默认全部
	//	newList = lists
	//} else {
	tmpPages := make(map[int32]*forms.Menu)

	for _, item := range lists {
		if item.Meta.IsSuper {
			continue
		}
		if character.InSlice(rolePages, item.Id) {
			tmpPages[item.Id] = &forms.Menu{
				Id:        item.Id,
				Component: item.Component,
				Meta:      item.Meta,
				Name:      item.Name,
				Path:      item.Name,
				Redirect:  item.Redirect,
				Children:  []*forms.Menu{},
			}
		}
		if len(item.Children) > 0 {
			for _, children := range item.Children {
				if children.Meta.IsSuper {
					continue
				}
				if !character.InSlice(rolePages, children.Id) {
					continue
				}
				if _, ok2 := tmpPages[item.Id]; ok2 {
					tmpPages[item.Id].Children = append(tmpPages[item.Id].Children, children)
				} else {
					tmpPages[item.Id] = &forms.Menu{
						Id:        item.Id,
						Component: item.Component,
						Meta:      item.Meta,
						Name:      item.Name,
						Path:      item.Name,
						Redirect:  item.Redirect,
						Children:  []*forms.Menu{children},
					}
				}
			}
		}
	}

	for _, item := range tmpPages {
		sort.Slice(item.Children, func(i, j int) bool {
			return item.Children[i].Meta.Sort < item.Children[j].Meta.Sort
		})
		newList = append(newList, item)
	}
	//}

	// 排序
	sort.Slice(newList, func(i, j int) bool {
		return newList[i].Meta.Sort < newList[j].Meta.Sort
	})
	return newList, nil
}
