package model

import (
	"sort"
	"time"

	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"

	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
)

type SystemMenu struct {
	Id              int64                   `json:"id"`
	Name            string                  `json:"name"`
	Title           string                  `json:"title"`
	Path            string                  `json:"path"`
	Icon            string                  `json:"icon"`
	Component       string                  `json:"component"`
	Redirect        string                  `json:"redirect"`
	Auths           string                  `json:"auths"`
	MenuType        pasturePb.MenuType_Kind `json:"menu_type"`
	ParentId        int64                   `json:"parent_id"`
	Rank            int32                   `json:"rank"`
	ExtraIcon       string                  `json:"extra_icon"`
	EnterTransition string                  `json:"enter_transition"`
	ActivePath      string                  `json:"active_path"`
	FrameSrc        string                  `json:"frame_src"`
	FrameLoading    pasturePb.IsShow_Kind   `json:"frame_loading"`
	Keepalive       pasturePb.IsShow_Kind   `json:"keepalive"`
	HiddenTag       pasturePb.IsShow_Kind   `json:"hidden_tag"`
	ShowLink        pasturePb.IsShow_Kind   `json:"show_link"`
	ShowParent      pasturePb.IsShow_Kind   `json:"show_parent"`
	IsShow          pasturePb.IsShow_Kind   `json:"is_show"`
	IsDelete        pasturePb.IsShow_Kind   `json:"is_delete"`
	CreatedAt       int64                   `json:"created_at"`
	UpdatedAt       int64                   `json:"updated_at"`
}

func (s *SystemMenu) TableName() string {
	return "system_menu"
}

func NewSystemMenu(req *operationPb.AddMenuRequest) *SystemMenu {
	return &SystemMenu{
		Name:      req.Name,
		Title:     req.Title,
		Path:      req.Path,
		Component: req.Component,
		Icon:      req.Icon,
		Redirect:  req.Redirect,
		ParentId:  int64(req.ParentId),
		IsShow:    pasturePb.IsShow_Ok,
		IsDelete:  pasturePb.IsShow_Ok,
	}
}

type SystemMenuSlice []*SystemMenu

func (s SystemMenuSlice) ToPB() []*pasturePb.SearchMenuRequest {
	res := make([]*pasturePb.SearchMenuRequest, len(s))
	for i, menu := range s {
		var frameLoading, keepalive, hiddenTag, showLink, showParent bool
		if menu.FrameLoading == pasturePb.IsShow_Ok {
			frameLoading = true
		}
		if menu.Keepalive == pasturePb.IsShow_Ok {
			keepalive = true
		}
		if menu.HiddenTag == pasturePb.IsShow_Ok {
			hiddenTag = true
		}
		if menu.ShowLink == pasturePb.IsShow_Ok {
			showLink = true
		}
		if menu.ShowParent == pasturePb.IsShow_Ok {
			showParent = true
		}

		res[i] = &pasturePb.SearchMenuRequest{
			Id:              int32(menu.Id),
			Name:            menu.Name,
			ParentId:        int32(menu.ParentId),
			MenuType:        menu.MenuType,
			Title:           menu.Title,
			Path:            menu.Path,
			IsShow:          menu.IsShow,
			Component:       menu.Component,
			Icon:            menu.Icon,
			Redirect:        menu.Redirect,
			Auths:           menu.Auths,
			Rank:            menu.Rank,
			ExtraIcon:       menu.ExtraIcon,
			EnterTransition: menu.EnterTransition,
			ActivePath:      menu.ActivePath,
			FrameSrc:        menu.FrameSrc,
			FrameLoading:    frameLoading,
			Keepalive:       keepalive,
			HiddenTag:       hiddenTag,
			ShowLink:        showLink,
			ShowParent:      showParent,
			CreatedAtFormat: time.Unix(menu.CreatedAt, 0).Format(LayoutTime),
			UpdatedAtFormat: time.Unix(menu.UpdatedAt, 0).Format(LayoutTime),
		}
	}
	return res
}

func (s SystemMenuSlice) ToTree() []*pasturePb.MenuTree {
	res := make([]*pasturePb.MenuTree, len(s))
	if 0 == len(s) {
		return res
	}
	// 正排序
	sort.Slice(s, func(i, j int) bool {
		return s[i].ParentId < s[j].ParentId
	})

	for i, v := range s {
		res[i] = &pasturePb.MenuTree{
			Id:       int32(v.Id),
			Path:     v.Path,
			ParentId: int32(v.ParentId),
			Name:     v.Name,
			Meta: &pasturePb.MenuMeta{
				Icon:     v.Icon,
				Title:    v.Title,
				Rank:     v.Rank,
				Roles:    []string{"admin"},
				ShowLink: v.ShowLink == pasturePb.IsShow_Ok,
			},
			Children: make([]*pasturePb.MenuTree, 0),
		}
	}
	// 构建树
	return buildTree(res)
}

func buildTree(menuTreeList []*pasturePb.MenuTree) []*pasturePb.MenuTree {
	tree := make([]*pasturePb.MenuTree, 0)
	for _, menu := range menuTreeList {
		if menu.ParentId == 0 {
			tree = append(tree, menu)
		} else {
			parent := findByID(menuTreeList, menu.ParentId)
			if parent != nil {
				parent.Children = append(parent.Children, menu)
			}
		}
	}
	return tree
}

func findByID(menuTreeList []*pasturePb.MenuTree, id int32) *pasturePb.MenuTree {
	for _, v := range menuTreeList {
		if id == v.Id {
			return v
		}
		if child := findByID(v.Children, id); child != nil {
			return child
		}
	}
	return nil
}

func BooleanToIsShow(isShow bool) pasturePb.IsShow_Kind {
	showKind := pasturePb.IsShow_No
	if isShow {
		showKind = pasturePb.IsShow_Ok
	}
	return showKind
}