package role

import (
	"context"
	v1 "kami/api/authority/v1"
	"kami/api/commonApi"
	"kami/internal/model"
	"kami/internal/service"
	"kami/internal/systemV2/dao"
	"kami/internal/systemV2/model/do"
	"kami/internal/systemV2/model/entity"
	"kami/utility/lib/libErr"

	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
)

func init() {
	service.RegisterMenu(New())
}

func New() *sMenu {
	return &sMenu{}
}

type sMenu struct{}

// GetMenuTree 挂载数据
func (s *sMenu) GetMenuTree(ctx context.Context) (resModels []*model.SysAuthRule, err error) {
	err = g.Try(ctx, func(ctx context.Context) {
		var models []entity.V2SysAuthRule
		err = dao.V2SysAuthRule.Ctx(ctx).Scan(&models)
		resModels = s.reStructData(resModels, models)
	})
	return
}

// 重新组织数据
func (s *sMenu) reStructData(rules []*model.SysAuthRule, authRule []entity.V2SysAuthRule) []*model.SysAuthRule {
	for _, sysAuthRule := range authRule {
		if sysAuthRule.Pid == 0 {
			rules = append(rules, &model.SysAuthRule{
				SysAuthRule: v1.SysAuthRule{
					CommonIntId: commonApi.CommonIntId{ID: sysAuthRule.Id},
					Name:        sysAuthRule.Name,
					Title:       sysAuthRule.Title,
					MenuType:    sysAuthRule.MenuType,
					Weigh:       sysAuthRule.Weigh,
					IsHide:      sysAuthRule.IsHide,
					Path:        sysAuthRule.Path,
					IdAdmin:     sysAuthRule.IdAdmin,
					Component:   sysAuthRule.Component,
				},
				Children: make([]*model.SysAuthRule, 0),
			})
		} else {
			for _, rule := range rules {
				s.mountData(rule, sysAuthRule)
			}
		}
	}
	return rules
}

// 重新组织数据
func (s *sMenu) mountData(rules *model.SysAuthRule, authRule entity.V2SysAuthRule) {
	if rules.ID == authRule.Pid {
		rules.Children = append(rules.Children, &model.SysAuthRule{
			SysAuthRule: v1.SysAuthRule{
				CommonIntId: commonApi.CommonIntId{ID: authRule.Id},
				Name:        authRule.Name,
				Title:       authRule.Title,
				MenuType:    authRule.MenuType,
				Weigh:       authRule.Weigh,
				IsHide:      authRule.IsHide,
				Path:        authRule.Path,
				IdAdmin:     authRule.IdAdmin,
				Component:   authRule.Component,
			},
			Children: make([]*model.SysAuthRule, 0),
		})
		rules.Children = append(rules.Children, &model.SysAuthRule{})

	} else if len(rules.Children) != 0 {
		for _, child := range rules.Children {
			s.mountData(child, authRule)
		}
	}
}

func (s *sMenu) AddMenu(ctx context.Context, model model.SysAuthRuleInput) (err error) {
	err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		return g.Try(ctx, func(ctx context.Context) {
			_, err2 := dao.V2SysAuthRule.Ctx(ctx).TX(tx).Save(model)
			libErr.ErrIsNil(ctx, err2)
		})
	})
	return
}

func (s *sMenu) UpdateMenu(ctx context.Context, model model.SysAuthRuleWithIDInput) (err error) {
	err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		return g.Try(ctx, func(ctx context.Context) {
			_, err2 := dao.V2SysAuthRule.Ctx(ctx).TX(tx).
				WherePri(dao.V2SysAuthRule.Columns().Id, model.ID).
				Update(do.V2SysAuthRule{
					Pid:       model.PID,
					Name:      model.Name,
					Title:     model.Title,
					MenuType:  model.MenuType,
					Weigh:     model.Weigh,
					IsHide:    model.IsHide,
					Path:      model.Path,
					IdAdmin:   model.IsAdmin,
					Component: model.Component,
				})
			libErr.ErrIsNil(ctx, err2)
		})
	})
	return
}

func (s *sMenu) DeleteMenu(ctx context.Context, ID uint) (err error) {
	err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		return g.Try(ctx, func(ctx context.Context) {
			_, err2 := dao.V2SysAuthRule.Ctx(ctx).TX(tx).
				WherePri(dao.V2SysAuthRule.Columns().Id, ID).
				Delete()
			libErr.ErrIsNil(ctx, err2)
		})
	})
	return
}

func (s *sMenu) DeleteMenuListByID(ctx context.Context, IDList []uint) (err error) {
	err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		return g.Try(ctx, func(ctx context.Context) {
			_, err2 := dao.V2SysAuthRule.Ctx(ctx).TX(tx).
				WhereIn(dao.V2SysAuthRule.Columns().Id, IDList).
				Delete()
			libErr.ErrIsNil(ctx, err2)
		})
	})
	return
}

// GetMenuListByID 通过ID查找所有的子节点
func (s *sMenu) GetMenuListByID(ctx context.Context, ID uint) (resModels []entity.V2SysAuthRule, err error) {
	resModels = make([]entity.V2SysAuthRule, 0)
	err = g.Try(ctx, func(ctx context.Context) {
		var models []entity.V2SysAuthRule
		err = dao.V2SysAuthRule.Ctx(ctx).
			Scan(&models)

		for _, rule := range models {
			if rule.Id == ID {
				resModels = append(resModels, rule)
			} else {
				// 深层复制
				resCopyModels := make([]entity.V2SysAuthRule, len(resModels))
				copy(resCopyModels, resModels)
				for _, resModel := range resCopyModels {
					if resModel.Id == rule.Pid {
						resModels = append(resModels, rule)
					}
				}
			}
		}
	})
	return
}
