package system

import (
	"context"
	"time"

	"github.com/beego/beego/v2/client/orm"
	"github.com/beego/beego/v2/core/logs"
)

const SECOND_MENU_INFO = "second_menu_info"

type SecondMenuInfo struct {
	Id             int
	FirstMenuOrder int
	FirstMenuUid   string
	FirstMenu      string
	MenuOrder      int
	SecondMenuUid  string
	SecondMenu     string
	SecondRouter   string
	Creater        string
	Status         string
	CreateTime     time.Time
	UpdateTime     time.Time
}

type SecondMenuSlice []SecondMenuInfo

func (sm SecondMenuSlice) Len() int {
	return len(sm)
}

func (sm SecondMenuSlice) Swap(i, j int) {
	sm[i], sm[j] = sm[j], sm[i]
}

func (sm SecondMenuSlice) Less(i, j int) bool {
	if sm[i].FirstMenuOrder == sm[j].FirstMenuOrder {
		return sm[i].MenuOrder < sm[j].MenuOrder
	}
	return sm[i].FirstMenuOrder < sm[j].FirstMenuOrder
}

func GetSecondMenuInfoByMenuOrder(ctx context.Context, menuOrder int, firstMenuUid string) SecondMenuInfo {
	o := orm.NewOrm()
	var secondMenuInfo SecondMenuInfo
	_, err := o.QueryTable(SECOND_MENU_INFO).Filter("first_menu_uid", firstMenuUid).Filter("menu_order", menuOrder).Limit(1).AllWithCtx(ctx, &secondMenuInfo)
	if err != nil {
		logs.Error("get second menu info by menu order fail: ", err)
	}
	return secondMenuInfo
}

func GetSecondMenuLenByFirstMenuUid(ctx context.Context, firstMenuUid string) int {
	o := orm.NewOrm()
	cnt, err := o.QueryTable(SECOND_MENU_INFO).Filter("first_menu_uid", firstMenuUid).CountWithCtx(ctx)
	if err != nil {
		logs.Error("get second menu len by first menu uid fail: ", err)
	}
	return int(cnt)
}

func GetSecondMenuList(ctx context.Context) []SecondMenuInfo {
	o := orm.NewOrm()
	var secondMenuList []SecondMenuInfo
	_, err := o.QueryTable(SECOND_MENU_INFO).Limit(-1).OrderBy("-update_time").AllWithCtx(ctx, &secondMenuList)
	if err != nil {
		logs.Error("get second menu list fail: ", err)
	}
	return secondMenuList
}

func GetSecondMenuInfoBySecondMenuUid(ctx context.Context, secondMenuUid string) SecondMenuInfo {
	o := orm.NewOrm()
	var secondMenuInfo SecondMenuInfo
	_, err := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu_uid", secondMenuUid).Limit(1).AllWithCtx(ctx, &secondMenuInfo)
	if err != nil {
		logs.Error("get scond menu info by second menu uid fail: ", err)
	}
	return secondMenuInfo
}

func GetSecondMenuInfoBySecondMenuUids(ctx context.Context, secondMenuUids []string) []SecondMenuInfo {
	secondMenuInfoList := make([]SecondMenuInfo, 0)
	for _, v := range secondMenuUids {
		sm := GetSecondMenuInfoBySecondMenuUid(ctx, v)
		secondMenuInfoList = append(secondMenuInfoList, sm)
	}
	return secondMenuInfoList
}

func GetSecondMenuListByFirstMenuUid(ctx context.Context, firstMenuUid string) []SecondMenuInfo {
	o := orm.NewOrm()
	var secondMenuList []SecondMenuInfo
	_, err := o.QueryTable(SECOND_MENU_INFO).Filter("first_menu_uid", firstMenuUid).Limit(-1).OrderBy("-update_time").AllWithCtx(ctx, &secondMenuList)
	if err != nil {
		logs.Error("get second menu list by first menu uid fail: ", err)
	}
	return secondMenuList
}

func GetSecondMenuLenByMap(ctx context.Context, params map[string]string) int {
	o := orm.NewOrm()
	qs := o.QueryTable(SECOND_MENU_INFO)
	for k, v := range params {
		qs = qs.Filter(k, v)
	}
	cnt, err := qs.Limit(-1).CountWithCtx(ctx)
	if err != nil {
		logs.Error("get second menu len by map fail: ", err)
	}
	return int(cnt)
}

func GetSecondMenuByMap(ctx context.Context, params map[string]string, displayCount, offset int) []SecondMenuInfo {
	o := orm.NewOrm()
	var secondMenuList []SecondMenuInfo
	qs := o.QueryTable(SECOND_MENU_INFO)
	for k, v := range params {
		if len(v) > 0 {
			qs = qs.Filter(k, v)
		}
	}
	_, err := qs.Limit(displayCount, offset).OrderBy("-update_time").AllWithCtx(ctx, &secondMenuList)
	if err != nil {
		logs.Error("get second menu by map fail: ", err)
	}
	return secondMenuList
}
func InsertSecondMenu(ctx context.Context, secondMenuInfo SecondMenuInfo) bool {
	o := orm.NewOrm()
	_, err := o.InsertWithCtx(ctx, &secondMenuInfo)
	if err != nil {
		logs.Error("insert second menu fail: ", err)
		return false
	}
	return true
}

func SecondMenuIsExists(ctx context.Context, seconfMenu string) bool {
	o := orm.NewOrm()
	exist := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu", seconfMenu).ExistWithCtx(ctx)
	return exist
}

func SecondMenuUidIsExists(ctx context.Context, secondMenuUid string) bool {
	o := orm.NewOrm()
	exist := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu_uid", secondMenuUid).ExistWithCtx(ctx)
	return exist
}

func SecondRouterExists(ctx context.Context, secondRouter string) bool {
	o := orm.NewOrm()
	exist := o.QueryTable(SECOND_MENU_INFO).Filter("second_router", secondRouter).ExistWithCtx(ctx)
	return exist
}

func DeleteSecondMenuByFirstMenuUid(ctx context.Context, firstMenuUid string) bool {
	o := orm.NewOrm()
	num, err := o.QueryTable(SECOND_MENU_INFO).Filter("first_menu_uid", firstMenuUid).DeleteWithCtx(ctx)
	if err != nil {
		logs.Error("delete second menu by first menu uid fail: ", err)
		return false
	}
	logs.Info("delete second menu by first menu uid success, num: ", num)
	return true
}

func DeleteSecondMenuBySecondMenuUid(ctx context.Context, secondMenuUid string) bool {
	o := orm.NewOrm()
	num, err := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu_uid", secondMenuUid).DeleteWithCtx(ctx)
	if err != nil {
		logs.Error("delete second menu by second menu uid fail: ", err)
		return false
	}
	logs.Info("delete second menu by second menu uid success, num: ", num)
	return true
}

func UpdateSecondMenuOrderBySecondUid(ctx context.Context, secondUid string, order int) {
	o := orm.NewOrm()
	_, err := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu_uid", secondUid).UpdateWithCtx(ctx, orm.Params{"menu_order": order})
	if err != nil {
		logs.Error("update second menu order by second menu uid fail: ", err)
	}
}

func UpdateSecondMenu(ctx context.Context, secondMenu SecondMenuInfo) {
	o := orm.NewOrm()
	_, err := o.UpdateWithCtx(ctx, &secondMenu)
	if err != nil {
		logs.Error("update second menu for first order fail: ", err)
	}
}
