package permission

import (
	"context"

	"gateway/internal/model/permission/domain/enum"
	domperm "gateway/internal/model/permission/domain/usecase"
	"gateway/internal/svc"
	"gateway/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetPermissionCatalogLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// NewGetPermissionCatalogLogic returns the catalog reader logic.
func NewGetPermissionCatalogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPermissionCatalogLogic {
	return &GetPermissionCatalogLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// GetPermissionCatalog reads the platform-wide catalog (tree + flat list).
func (l *GetPermissionCatalogLogic) GetPermissionCatalog(req *types.PermissionCatalogQuery) (*types.PermissionCatalogData, error) {
	if l.svcCtx.PermissionCatalog == nil {
		return nil, errb.SysNotImplemented("permission module not configured")
	}
	query := &domperm.CatalogQuery{
		OnlyOpen: req.Status == string(enum.StatusOpen),
	}
	if req.Type != "" {
		t := enum.PermissionType(req.Type)
		query.Type = &t
	}
	resp := &types.PermissionCatalogData{}
	if req.Tree {
		tree, err := l.svcCtx.PermissionCatalog.GetCatalogTree(l.ctx, query)
		if err != nil {
			return nil, err
		}
		resp.Tree = mapNodes(tree)
		return resp, nil
	}
	list, err := l.svcCtx.PermissionCatalog.List(l.ctx, query)
	if err != nil {
		return nil, err
	}
	resp.List = make([]types.PermissionNode, 0, len(list))
	for _, perm := range list {
		resp.List = append(resp.List, types.PermissionNode{
			ID:          perm.ID.Hex(),
			Parent:      perm.Parent,
			Name:        perm.Name,
			HTTPMethods: perm.HTTPMethods,
			HTTPPath:    perm.HTTPPath,
			Status:      perm.Status.String(),
			Type:        perm.Type.String(),
		})
	}
	return resp, nil
}

func mapNodes(nodes []*domperm.PermissionTreeNode) []types.PermissionNode {
	if len(nodes) == 0 {
		return nil
	}
	out := make([]types.PermissionNode, 0, len(nodes))
	for _, node := range nodes {
		out = append(out, types.PermissionNode{
			ID:          node.ID,
			Parent:      node.Parent,
			Name:        node.Name,
			HTTPMethods: node.HTTPMethods,
			HTTPPath:    node.HTTPPath,
			Status:      node.Status.String(),
			Type:        node.Type.String(),
			Children:    mapNodes(node.Children),
		})
	}
	return out
}
