package system

import (
	"errors"
	"gorm.io/gorm"
	"server/global"
)

type SysBaseMenu struct {
	global.GVA_MODEL
	MenuLevel     uint                                       `json:"-"`
	ParentId      uint                                       `json:"parentId" gorm:"comment:父菜单ID"`     // 父菜单ID
	Path          string                                     `json:"path" gorm:"comment:路由path"`        // 路由path
	Name          string                                     `json:"name" gorm:"comment:路由name"`        // 路由name
	Hidden        bool                                       `json:"hidden" gorm:"comment:是否在列表隐藏"`     // 是否在列表隐藏
	Component     string                                     `json:"component" gorm:"comment:对应前端文件路径"` // 对应前端文件路径
	Sort          int                                        `json:"sort" gorm:"comment:排序标记"`          // 排序标记
	Meta          `json:"meta" gorm:"embedded;comment:附加属性"` // 附加属性
	SysAuthoritys []SysAuthority                             `json:"authoritys" gorm:"many2many:sys_authority_menus;"`
	Children      []SysBaseMenu                              `json:"children" gorm:"-"`
	Parameters    []SysBaseMenuParameter                     `json:"parameters"`
	MenuBtn       []SysBaseMenuBtn                           `json:"menuBtn"`
}

type Meta struct {
	ActiveName  string `json:"activeName" gorm:"comment:高亮菜单"`
	KeepAlive   bool   `json:"keepAlive" gorm:"comment:是否缓存"`           // 是否缓存
	DefaultMenu bool   `json:"defaultMenu" gorm:"comment:是否是基础路由（开发中）"` // 是否是基础路由（开发中）
	Title       string `json:"title" gorm:"comment:菜单名"`                // 菜单名
	Icon        string `json:"icon" gorm:"comment:菜单图标"`                // 菜单图标
	CloseTab    bool   `json:"closeTab" gorm:"comment:自动关闭tab"`         // 自动关闭tab
}

type SysBaseMenuParameter struct {
	global.GVA_MODEL
	SysBaseMenuID uint
	Type          string `json:"type" gorm:"comment:地址栏携带参数为params还是query"` // 地址栏携带参数为params还是query
	Key           string `json:"key" gorm:"comment:地址栏携带参数的key"`            // 地址栏携带参数的key
	Value         string `json:"value" gorm:"comment:地址栏携带参数的值"`            // 地址栏携带参数的值
}

func (SysBaseMenu) TableName() string {
	return "sys_base_menus"
}

// TODO:菜单查询

// QueryBaseMenuAndParametersByMenuId 查询菜单和参数 按菜单id
func QueryBaseMenuAndParametersByMenuId(menuIds []string) (baseMenu []SysBaseMenu, err error) {
	err = global.GVA_DB.Where("id in (?)", menuIds).Order("sort").Preload("Parameters").Find(&baseMenu).Error
	return
}

// QueryBaseMenuByName 查询菜单 按名字
func QueryBaseMenuByName(name string) (baseMenu SysBaseMenu, err error) {
	err = global.GVA_DB.Where("name = ?", name).First(&baseMenu).Error
	return
}

// QueryBaseMenuAndMenuBtnAndParameters 查询菜单和菜单按钮和参数
func QueryBaseMenuAndMenuBtnAndParameters() (allMenus []SysBaseMenu, err error) {
	err = global.GVA_DB.Order("sort").Preload("MenuBtn").Preload("Parameters").Find(&allMenus).Error
	return
}

// QueryBaseMenuByIdAndDefaultRouter 查询菜单 按菜单id和默认路由
func QueryBaseMenuByIdAndDefaultRouter(defaultRouter string, menuIds []string) (allMenus []SysBaseMenu, err error) {
	err = global.GVA_DB.First(&allMenus, "name = ? and id in (?)", defaultRouter, menuIds).Error
	return
}

func QueryBaseMenuAndMenuBtnAndParameterById(id int) (menu SysBaseMenu, err error) {
	err = global.GVA_DB.Preload("MenuBtn").Preload("Parameters").Where("id = ?", id).First(&menu).Error
	return
}

// TODO:菜单新增

// CreateBaseMenu 创建菜单
func (bm SysBaseMenu) CreateBaseMenu() error {
	return global.GVA_DB.Create(&bm).Error
}

// TODO:菜单修改

func (bm SysBaseMenu) UpdateBaseMenu() (err error) {
	var oldMenu SysBaseMenu

	err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		tx.Where("id = ?", bm.ID).Find(&oldMenu)
		if oldMenu.Name != bm.Name {
			if !errors.Is(tx.Where("id <> ? AND name = ?", bm.ID, bm.Name).First(&SysBaseMenu{}).Error, gorm.ErrRecordNotFound) {
				global.GVA_LOG.Debug("存在相同name修改失败")
				return errors.New("存在相同name修改失败")
			}
		}
		txErr := tx.Unscoped().Delete(&SysBaseMenuParameter{}, "sys_base_menu_id = ?", bm.ID).Error
		if txErr != nil {
			global.GVA_LOG.Debug(txErr.Error())
			return txErr
		}
		txErr = tx.Unscoped().Delete(&SysBaseMenuBtn{}, "sys_base_menu_id = ?", bm.ID).Error
		if txErr != nil {
			global.GVA_LOG.Debug(txErr.Error())
			return txErr
		}
		if len(bm.Parameters) > 0 {
			for k := range bm.Parameters {
				bm.Parameters[k].SysBaseMenuID = bm.ID
			}
			txErr = tx.Create(&bm.Parameters).Error
			if txErr != nil {
				global.GVA_LOG.Debug(txErr.Error())
				return txErr
			}
		}

		if len(bm.MenuBtn) > 0 {
			for k := range bm.MenuBtn {
				bm.MenuBtn[k].SysBaseMenuID = bm.ID
			}
			txErr = tx.Create(&bm.MenuBtn).Error
			if txErr != nil {
				global.GVA_LOG.Debug(txErr.Error())
				return txErr
			}
		}

		txErr = tx.Model(&oldMenu).Updates(bm).Error
		if txErr != nil {
			global.GVA_LOG.Debug(txErr.Error())
			return txErr
		}
		return nil
	})
	return err
}

// TODO:菜单删除
