package domain

import (
	"errors"
	"fmt"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/constant"
	"strconv"
	"strings"
)

const PathSegment = ","

var (
	Catalog MenuType = "catalog" // 目录
	Menu_   MenuType = "menu"    // 菜单
	Button  MenuType = "button"  // 按钮
)

var (
	ErrorMenuType = errors.New(fmt.Sprintf("菜单类型有误 可选值 %v、%v、%v", Catalog, Menu_, Button))
)

// 菜单启用状态 结合用户菜单权限
const (
	MenuStatusEnable  = 1 // 菜单启用
	MenuStatusDisable = 2 // 菜单禁用
)

// 菜单公开状态
const (
	MenuPublic  = 1 // 菜单公开
	MenuPrivate = 2 // 菜单未公开
)

const (
	WebMenuCode = "web"
	AppMenuCode = "app"
)

// 菜单类型
type MenuType string

// 系统菜单
type Menu struct {
	// 菜单编号
	MenuId int64 `json:"menuId,omitempty"`
	// 父级id
	ParentId int64 `json:"parentId"`
	// 菜单名称
	MenuName string `json:"menuName,omitempty"`
	// 菜单别名
	MenuAlias string `json:"menuAlias,omitempty"`
	// 菜单编码 SYSTEM_USER_EDIT / 100101 (字符编码)
	Code string `json:"code,omitempty"`
	// 权限编码 user:edit
	AccessCode string `json:"accessCode,omitempty"`
	// 菜单类型 (目录catalog、菜单menu、按钮button)
	MenuType string `json:"menuType,omitempty"`
	// 菜单图标
	Icon string `json:"icon,omitempty"`
	// 排序
	Sort int `json:"sort,omitempty"`
	// 菜单说明
	Remark string `json:"remark,omitempty"`
	// 菜单类别 (web:1、app:2)
	Category string `json:"category,omitempty"`
	// 路径节点路径("0,11,12,")
	ParentPath string `json:"parentPath,omitempty"`
	// 菜单是否公开状态,[1:显示],[2:隐藏],默认显示
	IsPublish int `json:"isPublish,omitempty"`
	// 启用状态(启用:1 禁用:2),默认启用
	EnableStatus int `json:"enableStatus,omitempty"`

	// 父级菜单名称
	ParentMenuName string `json:"parentMenuName,omitempty"`
}

type MenuRepository interface {
	Save(menu *Menu) (*Menu, error)
	Remove(menu *Menu) (*Menu, error)
	FindOne(queryOptions map[string]interface{}) (*Menu, error)
	Find(queryOptions map[string]interface{}) (int64, []*Menu, error)
}

func (menu *Menu) Identify() interface{} {
	if menu.MenuId == 0 {
		return nil
	}
	return menu.MenuId
}

func (menu *Menu) Update(data map[string]interface{}) error {
	if parentId, ok := data["parentId"]; ok {
		menu.ParentId = parentId.(int64)
	}
	if menuName, ok := data["menuName"]; ok {
		menu.MenuName = menuName.(string)
	}
	if code, ok := data["code"]; ok {
		menu.Code = code.(string)
	}
	if accessCode, ok := data["accessCode"]; ok {
		menu.AccessCode = accessCode.(string)
	}
	if menuType, ok := data["menuType"]; ok {
		menu.MenuType = menuType.(string)
	}
	if icon, ok := data["icon"]; ok {
		menu.Icon = icon.(string)
	}
	if sort, ok := data["sort"]; ok {
		menu.Sort = sort.(int)
	}
	if desc, ok := data["desc"]; ok {
		menu.Remark = desc.(string)
	}
	//if category, ok := data["category"]; ok {
	//	menu.Category = category.(string)
	//}
	//if fullPath, ok := data["fullPath"]; ok {
	//	menu.ParentPath = parentPath.(string)
	//}
	if isPublish, ok := data["isPublish"]; ok {
		menu.IsPublish = isPublish.(int)
	}
	if enableStatus, ok := data["enableStatus"]; ok {
		menu.EnableStatus = enableStatus.(int)
	}
	return nil
}

/*****   0.基础模块函数  *****/

// GetCategory 获取菜单类别 1.web 2.app
func (menu *Menu) GetCategory() string {
	if menu.Category == "" {
		return strconv.Itoa(int(menu.MenuId))
	}
	return menu.Category
}

func (menu *Menu) UpdateParentPath(old, new string) {
	if !strings.Contains(menu.ParentPath, old) {
		return
	}
	menu.ParentPath = strings.Replace(menu.ParentPath, old, new, 1)
}

func (menu *Menu) ValidMenuType() bool {
	mt := MenuType(menu.MenuType)
	if mt == Catalog || mt == Menu_ || mt == Button {
		return true
	}
	return false
}

func (menu *Menu) SetPublic(status int) error {
	if !(status == MenuPublic || status == MenuPrivate) {
		return fmt.Errorf("非法的公开状态: %v", status)
	}
	menu.IsPublish = status
	return nil
}

/*****   1.实现树  *****/
/*1.1 实现树的方法*/
// GetParentPath 获取菜单路径
func (menu *Menu) GetParentPath() string {
	if menu.ParentId == 0 {
		return ""
	}
	if len(menu.ParentPath) > 0 {
		return fmt.Sprintf("%v%v%v", menu.ParentPath, PathSegment, menu.MenuId)
	}
	return fmt.Sprintf("%v", menu.MenuId)
}

// GetFullPath 获取菜单全路径
func (menu *Menu) GetFullPath() string {
	if menu.ParentId == 0 {
		return ""
	}
	if len(menu.ParentPath) > 0 {
		return fmt.Sprintf("%v%v%v", menu.ParentPath, PathSegment, menu.MenuId)
	}
	return fmt.Sprintf("%v", menu.MenuId)
}

func (menu *Menu) PID() string {
	return menu.ParentPath
}
func (menu *Menu) ID() string {
	return menu.GetFullPath()
}

/*****   2.缓存  *****/
/*2.1 缓存键值*/
func (m *Menu) CacheKeyFunc() string {
	if constant.DISABLE_REPOSITORY_CACHE {
		return ""
	}
	if m.MenuId == 0 {
		return ""
	}
	return fmt.Sprintf("%v:cache:menu:id:%v", constant.CACHE_PREFIX, m.MenuId)
}