package models

import (
	"errors"
	"fmt"
	orm "go-admin/common/global"
	"go-admin/tools"
)

const (
	PurchasePrice     = "erp:stock:stockDetails:list:purchasePrice"     // 库存详情-入库采购价
	EmployeeCostPrice = "erp:stock:stockDetails:list:employeeCostPrice" // 库存详情-入库员工成本价

	PriceMenu           = "erp:purchase:purchaseDetails:list:price"            // 采购/退货价
	EmployeePriceMenu   = "erp:purchase:purchaseDetails:list:employee_price"   // 员工成本价
	DifferencePriceMenu = "erp:purchase:purchaseDetails:list:difference_price" // 差额

	SalesProfitMenu = "erp:retail:storeMangement:salesProfit" // 门店经营-销售毛利
	StaffProfitMenu = "erp:retail:storeMangement:staffProfit" // 门店经营-员工毛利

	SalesCostMenu            = "erp:retail:retailRemittance:salesCost"            // 商品零售毛利汇总-销售成本
	EmployeeCostMenu         = "erp:retail:retailRemittance:staffCost"            // 商品零售毛利汇总-员工成本
	SalesMarginMenu          = "erp:retail:retailRemittance:salesMargin"          // 商品零售毛利汇总-销售毛利
	EmployeeMarginMenu       = "erp:retail:retailRemittance:employeeMargin"       // 商品零售毛利汇总-员工毛利
	GrossMarginsMenu         = "erp:retail:retailRemittance:grossMargins"         // 商品零售毛利汇总-销售毛利率
	EmployeeGrossMarginsMenu = "erp:retail:retailRemittance:employeeGrossMargins" // 商品零售毛利汇总-员工毛利率

	DetailWholesalePriceMenu   = "erp:retail:reportForm:retailDetails:wholesalePrice" // 零售明细-采购单价
	DetailEmployeeCostMenu     = "erp:retail:reportForm:retailDetails:staffPrice"     // 零售明细-员工成本价
	DetailSalesProfitMenu      = "erp:retail:reportForm:retailDetails:salesProfit"    // 零售明细-销售毛利
	DetailStaffProfitMenu      = "erp:retail:reportForm:retailDetails:staffProfit"    // 零售明细-员工毛利
	DetailTotalSalesProfitMenu = "erp:retail:reportForm:retailDetails:totalSales"     // 零售明细-订单总销售毛利
	DetailTotalStaffProfitMenu = "erp:retail:reportForm:retailDetails:totalStaff"     // 零售明细-订单总员工毛利
	DetailSalesProfitPerMenu   = "erp:retail:reportForm:retailDetails:salesProfitPer" // 零售明细-销售毛利提成
	DetailStaffProfitPerMenu   = "erp:retail:reportForm:retailDetails:staffProfitPer" // 零售明细-员工毛利提成
	DetailSalesmanPerMenu      = "erp:retail:reportForm:retailDetails:salesmanPer"    // 零售明细-销售员提成
	DetailStorePerMenu         = "erp:retail:reportForm:retailDetails:storePer"       // 零售明细-门店提成

	UserInfoListMenu = "user:export:tel" // 所有用户-手机号

	PrivilegeMemberMenu = "user:exclusive:member:tel" // 零售尊享会员-手机号

	InviteRecordListMenu = "user:member:invitation:tel" // 会员邀请记录-手机号
)

type Menu struct {
	MenuId     int    `json:"menuId" gorm:"primary_key;AUTO_INCREMENT"`
	MenuName   string `json:"menuName" gorm:"size:128;"`
	Title      string `json:"title" gorm:"size:128;"`
	Icon       string `json:"icon" gorm:"size:128;"`
	Path       string `json:"path" gorm:"size:128;"`
	Paths      string `json:"paths" gorm:"size:128;"`
	MenuType   string `json:"menuType" gorm:"size:1;"`
	Action     string `json:"action" gorm:"size:16;"`
	Permission string `json:"permission" gorm:"size:255;"`
	ParentId   int    `json:"parentId" gorm:"size:11;"`
	NoCache    bool   `json:"noCache" gorm:"size:8;"`
	Breadcrumb string `json:"breadcrumb" gorm:"size:255;"`
	Component  string `json:"component" gorm:"size:255;"`
	Sort       int    `json:"sort" gorm:"size:4;"`
	Visible    string `json:"visible" gorm:"size:1;"`
	CreateBy   string `json:"createBy" gorm:"size:128;"`
	UpdateBy   string `json:"updateBy" gorm:"size:128;"`
	IsFrame    string `json:"isFrame" gorm:"size:1;DEFAULT:0;"`
	DataScope  string `json:"dataScope" gorm:"-"`
	Params     string `json:"params" gorm:"-"`
	RoleId     int    `gorm:"-"`
	Children   []Menu `json:"children" gorm:"-"`
	IsSelect   bool   `json:"is_select" gorm:"-"`
	BaseModel
}

func (Menu) TableName() string {
	return "sys_menu"
}

type MenuLable struct {
	Id       int         `json:"id" gorm:"-"`
	Label    string      `json:"label" gorm:"-"`
	Children []MenuLable `json:"children" gorm:"-"`
}

type Menus struct {
	MenuId     int    `json:"menuId" gorm:"column:menu_id;primary_key;"`
	MenuName   string `json:"menuName" gorm:"column:menu_name"`
	Title      string `json:"title" gorm:"column:title"`
	Icon       string `json:"icon" gorm:"column:icon"`
	Path       string `json:"path" gorm:"column:path"`
	MenuType   string `json:"menuType" gorm:"column:menu_type"`
	Action     string `json:"action" gorm:"column:action"`
	Permission string `json:"permission" gorm:"column:permission"`
	ParentId   int    `json:"parentId" gorm:"column:parent_id"`
	NoCache    bool   `json:"noCache" gorm:"column:no_cache"`
	Breadcrumb string `json:"breadcrumb" gorm:"column:breadcrumb"`
	Component  string `json:"component" gorm:"column:component"`
	Sort       int    `json:"sort" gorm:"column:sort"`

	Visible  string `json:"visible" gorm:"column:visible"`
	Children []Menu `json:"children" gorm:"-"`

	CreateBy  string `json:"createBy" gorm:"column:create_by"`
	UpdateBy  string `json:"updateBy" gorm:"column:update_by"`
	DataScope string `json:"dataScope" gorm:"-"`
	Params    string `json:"params" gorm:"-"`
	BaseModel
}

func (Menus) TableName() string {
	return "sys_menu"
}

type MenuRole struct {
	Menus
	IsSelect bool `json:"is_select" gorm:"-"`
}

type MS []Menu

func (e *Menu) GetByMenuId() (Menu Menu, err error) {

	table := orm.Eloquent.Table(e.TableName())
	table = table.Where("menu_id = ?", e.MenuId)
	if err = table.Find(&Menu).Error; err != nil {
		return
	}
	return
}

func (e *Menu) SetMenu() (m []Menu, err error) {
	menulist, err := e.GetPage()

	m = make([]Menu, 0)
	for i := 0; i < len(menulist); i++ {
		if menulist[i].ParentId != 0 {
			continue
		}
		menusInfo := DiguiMenu(&menulist, menulist[i])

		m = append(m, menusInfo)
	}
	return
}

func DiguiMenu(menulist *[]Menu, menu Menu) Menu {
	list := *menulist

	min := make([]Menu, 0)
	for j := 0; j < len(list); j++ {

		if menu.MenuId != list[j].ParentId {
			continue
		}
		mi := Menu{}
		mi.MenuId = list[j].MenuId
		mi.MenuName = list[j].MenuName
		mi.Title = list[j].Title
		mi.Icon = list[j].Icon
		mi.Path = list[j].Path
		mi.MenuType = list[j].MenuType
		mi.Action = list[j].Action
		mi.Permission = list[j].Permission
		mi.ParentId = list[j].ParentId
		mi.NoCache = list[j].NoCache
		mi.Breadcrumb = list[j].Breadcrumb
		mi.Component = list[j].Component
		mi.Sort = list[j].Sort
		mi.Visible = list[j].Visible
		mi.CreatedAt = list[j].CreatedAt
		mi.Children = []Menu{}
		if mi.MenuId == 56 {
			continue
		}
		if mi.MenuType != "F" {
			ms := DiguiMenu(menulist, mi)
			min = append(min, ms)

		} else {
			min = append(min, mi)
		}

	}

	menu.Children = min
	return menu
}

func (e *Menu) SetMenuLable() (m []MenuLable, err error) {
	menulist, err := e.Get()

	m = make([]MenuLable, 0)
	for i := 0; i < len(menulist); i++ {
		if menulist[i].ParentId != 0 {
			continue
		}
		e := MenuLable{}
		e.Id = menulist[i].MenuId
		e.Label = menulist[i].Title
		menusInfo := DiguiMenuLable(&menulist, e)

		m = append(m, menusInfo)
	}
	return
}

func DiguiMenuLable(menulist *[]Menu, menu MenuLable) MenuLable {
	list := *menulist

	min := make([]MenuLable, 0)
	for j := 0; j < len(list); j++ {

		if menu.Id != list[j].ParentId {
			continue
		}
		mi := MenuLable{}
		mi.Id = list[j].MenuId
		mi.Label = list[j].Title
		mi.Children = []MenuLable{}
		if list[j].MenuType != "F" {
			ms := DiguiMenuLable(menulist, mi)
			min = append(min, ms)
		} else {
			min = append(min, mi)
		}

	}
	menu.Children = min
	return menu
}

func (e *Menu) SetMenuRole(rolename string) (m []Menu, err error) {
	fmt.Println("rolename:", rolename)
	menulist, err := e.GetByRoleName(rolename)

	m = make([]Menu, 0)
	for i := 0; i < len(menulist); i++ {
		if menulist[i].ParentId != 0 {
			continue
		}
		menusInfo := DiguiMenu(&menulist, menulist[i])

		m = append(m, menusInfo)
	}
	return
}

func (e *Menu) SetAdminMenuRole() (m []Menu, err error) {
	var menulist []Menu
	table := orm.Eloquent.Table(e.TableName()).Select("sys_menu.*").Where("menu_type in ('M','C')")
	if err = table.Order("sort").Find(&menulist).Error; err != nil {
		return
	}

	m = make([]Menu, 0)
	for i := 0; i < len(menulist); i++ {
		if menulist[i].ParentId != 0 {
			continue
		}
		menusInfo := DiguiMenu(&menulist, menulist[i])

		m = append(m, menusInfo)
	}
	return
}

func (e *MenuRole) Get() (Menus []MenuRole, err error) {
	table := orm.Eloquent.Table(e.TableName())
	if e.MenuName != "" {
		table = table.Where("menu_name = ?", e.MenuName)
	}
	if err = table.Order("sort").Find(&Menus).Error; err != nil {
		return
	}
	return
}

func (e *Menu) GetByRoleName(rolename string) (Menus []Menu, err error) {
	table := orm.Eloquent.Table(e.TableName()).Select("sys_menu.*").Joins("left join sys_role_menu on sys_role_menu.menu_id=sys_menu.menu_id")
	table = table.Where("sys_role_menu.role_name=? and menu_type in ('M','C')", rolename)
	if err = table.Order("sort").Find(&Menus).Error; err != nil {
		return
	}
	return
}

func (e *Menu) Get() (Menus []Menu, err error) {
	table := orm.Eloquent.Table(e.TableName())
	if e.MenuName != "" {
		table = table.Where("menu_name = ?", e.MenuName)
	}
	if e.Path != "" {
		table = table.Where("path = ?", e.Path)
	}
	if e.Action != "" {
		table = table.Where("action = ?", e.Action)
	}
	if e.MenuType != "" {
		table = table.Where("menu_type = ?", e.MenuType)
	}

	if err = table.Order("sort").Find(&Menus).Error; err != nil {
		//if err = table.Where("visible = 0").Order("sort").Find(&Menus).Error; err != nil {
		return
	}
	return
}

func (e *Menu) GetParentTitle() (title string, err error) {
	// 查询指定 title 的记录
	var menu Menu
	table := orm.Eloquent.Table(e.TableName())
	if err := table.Where("title = ? AND menu_type = ?", e.Title, "F").First(&menu).Error; err != nil {
		return "", err
	}

	// 递归查询父节点的 title 直到找到 parentId 为 0 的节点
	return getParentTitle(menu.ParentId)
}

// getParentTitle 递归查询父节点的 title
func getParentTitle(parentID int) (string, error) {
	if parentID == 0 {
		return "", nil
	}

	var parentMenu Menu
	table := orm.Eloquent.Table("sys_menu")
	// 查询父节点的记录
	if err := table.Where("menu_id = ?", parentID).First(&parentMenu).Error; err != nil {
		return "", err
	}

	// 递归查询父节点的 title
	parentTitle, err := getParentTitle(parentMenu.ParentId)
	if err != nil {
		return "", err
	}

	// 组合当前节点的 title 和父节点的 title，去掉开头的横杠
	if parentTitle != "" {
		return fmt.Sprintf("%s-%s", parentTitle, parentMenu.Title), nil
	}
	return parentMenu.Title, nil
}

func (e *Menu) GetPage() (Menus []Menu, err error) {
	table := orm.Eloquent.Table(e.TableName())
	if e.MenuName != "" {
		table = table.Where("menu_name = ?", e.MenuName)
	}
	if e.Title != "" {
		table = table.Where("title = ?", e.Title)
	}
	if e.Visible != "" {
		table = table.Where("visible = ?", e.Visible)
	}
	if e.MenuType != "" {
		table = table.Where("menu_type = ?", e.MenuType)
	}

	// 数据权限控制
	dataPermission := new(DataPermission)
	dataPermission.UserId, _ = tools.StringToInt(e.DataScope)
	table, err = dataPermission.GetDataScope("sys_menu", table)
	if err != nil {
		return nil, err
	}
	if err = table.Order("sort").Find(&Menus).Error; err != nil {
		return
	}
	return
}

func (e *Menu) Create() (id int, err error) {
	result := orm.Eloquent.Table(e.TableName()).Create(&e)
	if result.Error != nil {
		err = result.Error
		return
	}
	err = InitPaths(e)
	if err != nil {
		return
	}
	id = e.MenuId
	return
}

func InitPaths(menu *Menu) (err error) {
	parentMenu := new(Menu)
	if int(menu.ParentId) != 0 {
		orm.Eloquent.Table("sys_menu").Where("menu_id = ?", menu.ParentId).First(parentMenu)
		if parentMenu.Paths == "" {
			err = errors.New("父级paths异常，请尝试对当前节点父级菜单进行更新操作！")
			return
		}
		menu.Paths = parentMenu.Paths + "/" + tools.IntToString(menu.MenuId)
	} else {
		menu.Paths = "/0/" + tools.IntToString(menu.MenuId)
	}
	orm.Eloquent.Table("sys_menu").Where("menu_id = ?", menu.MenuId).Update("paths", menu.Paths)
	return
}

func (e *Menu) Update(id int) (update Menu, err error) {
	if err = orm.Eloquent.Table(e.TableName()).First(&update, id).Error; err != nil {
		return
	}

	//参数1:是要修改的数据
	//参数2:是修改的数据
	if err = orm.Eloquent.Table(e.TableName()).Model(&update).Updates(&e).Error; err != nil {
		return
	}
	err = InitPaths(e)
	if err != nil {
		return
	}
	return
}

func (e *Menu) Delete(id int) (success bool, err error) {
	if err = orm.Eloquent.Table(e.TableName()).Where("menu_id = ?", id).Delete(&Menu{}).Error; err != nil {
		success = false
		return
	}
	success = true
	return
}
