package system

import (
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"strings"
	"time"
)

// 需要特殊处理的菜单字段项
const (
	MenuSpecialHandleClassifyChildMenu  = "classifyList:cnClassify:childMenu"
	MenuSpecialHandleClassifyShowType   = "classifyList:cnClassify:showType"
	MenuSpecialHandleClassifyReportImgs = "classifyList:cnClassify:reportImgs"
	MenuSpecialHandleSandboxVariety     = "sandbox:variety"
)

type SysMenu struct {
	MenuId     int       `orm:"column(menu_id);pk"`
	ParentId   int       `description:"父级菜单ID"`
	Name       string    `description:"菜单名称或者按钮名称"`
	Sort       string    `description:"排序"`
	Path       string    `description:"路由地址"`
	IconPath   string    `description:"菜单图标地址"`
	Component  int       `description:"组件路径"`
	Hidden     int       `description:"是否隐藏:1-隐藏 0-显示"`
	IsLevel    int       `description:"是否为多级菜单:1,只有一级;2,有多级"`
	LevelPath  string    `description:"兼容以前menu表的字段"`
	MenuType   int       `description:"菜单类型: 0-菜单; 1-按钮; 2-字段(需要特殊处理)"`
	ButtonCode string    `description:"按钮/菜单唯一标识"`
	CreateTime time.Time `description:"创建时间"`
	ModifyTime time.Time `description:"更新时间"`
	Api        string    `description:"按钮相关api"`
	NameEn     string    `description:"菜单名称或者按钮名称(英文)"`
}

// GetSysMenuItemsByCondition 获取菜单列表
func GetSysMenuItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*SysMenu, err error) {
	o := orm.NewOrm()
	fields := strings.Join(fieldArr, ",")
	if len(fieldArr) == 0 {
		fields = `*`
	}
	order := `ORDER BY create_time DESC`
	if orderRule != "" {
		order = ` ORDER BY ` + orderRule
	}
	sql := fmt.Sprintf(`SELECT %s FROM sys_menu WHERE 1=1 %s %s`, fields, condition, order)
	_, err = o.Raw(sql, pars).QueryRows(&items)
	return
}

type MenuList struct {
	MenuId    int          `description:"导航唯一标识"`
	IsLevel   int          `description:"1,只有一级;2,有多级"`
	Name      string       `json:"name" description:"导航名称"`
	NameEn    string       `json:"name_en" description:"导航名称(英文)"`
	Path      string       `json:"path"`
	IconPath  string       `json:"icon_path"`
	LevelPath string       `json:"level_path"`
	Component string       `json:"component"`
	Hidden    bool         `json:"hidden"`
	Children  []*ChildMenu `json:"children"`
}

type ChildMenu struct {
	MenuId    int    `description:"导航唯一标识"`
	Name      string `json:"name" description:"导航名称"`
	NameEn    string `json:"name_en" description:"导航名称(英文)"`
	Path      string `json:"path"`
	Component string `json:"component"`
	IconPath  string `json:"icon_path"`
	Hidden    bool   `json:"hidden"`
}

type MenuListResp struct {
	List []*MenuList
}

func GetMenuList(roleId int) (items []*MenuList, err error) {
	sql := ` SELECT a.* FROM sys_menu AS a
			INNER JOIN sys_role_menu AS b ON a.menu_id=b.menu_id
			INNER JOIN sys_role AS c ON b.role_id=c.role_id
			WHERE c.role_id=?
			AND a.parent_id=0 
            ORDER BY sort ASC `
	_, err = orm.NewOrm().Raw(sql, roleId).QueryRows(&items)
	return
}

func GetMenuByParentId(roleId, parentId int) (items []*ChildMenu, err error) {
	sql := ` SELECT a.* FROM sys_menu AS a
			INNER JOIN sys_role_menu AS b ON a.menu_id=b.menu_id
			INNER JOIN sys_role AS c ON b.role_id=c.role_id
			WHERE c.role_id=?
			AND a.parent_id=? 
            ORDER BY sort ASC `
	_, err = orm.NewOrm().Raw(sql, roleId, parentId).QueryRows(&items)
	return
}

// GetMenuListByRoleIds 根据管理员多个角色查询菜单ID
func GetMenuListByRoleIds(roleIds string) (items []*MenuList, err error) {
	sql := ` SELECT DISTINCT a.* FROM sys_menu AS a
			INNER JOIN sys_role_menu AS b ON a.menu_id=b.menu_id AND b.type = 0
			INNER JOIN sys_role AS c ON b.role_id=c.role_id
			WHERE c.role_id in (` + roleIds + `)
			AND a.parent_id=0 
            ORDER BY sort ASC `
	_, err = orm.NewOrm().Raw(sql).QueryRows(&items)
	return
}

// GetMenuByParentIdRoleIds 根据管理员多个角色查询子菜单ID
func GetMenuByParentIdRoleIds(roleIds string, parentId int) (items []*ChildMenu, err error) {
	sql := ` SELECT DISTINCT a.* FROM sys_menu AS a
			INNER JOIN sys_role_menu AS b ON a.menu_id=b.menu_id AND b.type = 0
			INNER JOIN sys_role AS c ON b.role_id=c.role_id
			WHERE c.role_id in (` + roleIds + `)
			AND a.parent_id=? 
            ORDER BY a.sort ASC, create_time DESC, menu_id DESC`
	_, err = orm.NewOrm().Raw(sql, parentId).QueryRows(&items)
	return
}

// GetMenuButtonsByRoleId 获取角色按钮菜单
func GetMenuButtonsByRoleId(roleId int) (items []*SysMenu, err error) {
	sql := `SELECT
				r.*
			FROM
				sys_menu AS r
			JOIN sys_role_menu AS rm ON r.menu_id = rm.menu_id AND rm.type = 0
			WHERE
				rm.role_id = ? AND r.menu_type <> 0 AND r.hidden = 0
			ORDER BY
				r.sort ASC,
				r.create_time DESC`
	_, err = orm.NewOrm().Raw(sql, roleId).QueryRows(&items)
	return
}

// SysMenuButtonResp 按钮菜单响应体
type SysMenuButtonResp struct {
	MenuId     int    `description:"菜单ID"`
	ParentId   int    `description:"父级菜单ID"`
	Name       string `description:"菜单名称或者按钮名称"`
	MenuType   int    `description:"菜单类型: 0-菜单; 1-按钮"`
	ButtonCode string `description:"按钮唯一标识"`
}

// SysMenuListResp ETA商家菜单列表响应体
type SysMenuListResp struct {
	ChoiceList     []int          `description:"已选菜单"`
	HalfChoiceList []int          `description:"半选菜单-方便前端回显用的"`
	List           []*SysMenuItem `description:"菜单列表"`
}

// SysMenuItem ETA商家菜单
type SysMenuItem struct {
	MenuId     int
	ParentId   int            `description:"父级菜单ID"`
	Name       string         `description:"菜单名称或者按钮名称"`
	Sort       string         `description:"排序"`
	Path       string         `description:"路由地址"`
	IconPath   string         `description:"菜单图标地址"`
	Component  int            `description:"组件路径"`
	Hidden     int            `description:"是否隐藏:1-隐藏 0-显示"`
	MenuType   int            `description:"菜单类型: 0-菜单; 1-按钮; 2-字段(需要特殊处理)"`
	ButtonCode string         `description:"按钮/菜单唯一标识"`
	Children   []*SysMenuItem `description:"子菜单"`
}

// BusinessConf 商户配置表
type BusinessConf struct {
	ConfKey string `description:"配置Key"`
	ConfVal string `description:"配置值"`
}

// GetMenuButtonApisByRoleId 获取角色按钮api菜单
func GetMenuButtonApisByRoleId(roleId int) (items []*SysMenu, err error) {
	sql := `SELECT
				r.*
			FROM
				sys_menu AS r
			JOIN sys_role_menu AS rm ON r.menu_id = rm.menu_id 
			WHERE
				rm.role_id = ?
			ORDER BY
				r.sort ASC,
				r.create_time DESC`
	_, err = orm.NewOrm().Raw(sql, roleId).QueryRows(&items)
	return
}