package admin_role

import (
	"context"
	"sync"

	"sim-server/app/main/api/internal/svc"
	"sim-server/app/main/api/internal/types"
	"sim-server/app/main/model"
	"sim-server/common/xerr"

	"github.com/pkg/errors"
	"github.com/samber/lo"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/mr"
)

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

func NewGetRoleDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetRoleDetailLogic {
	return &GetRoleDetailLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetRoleDetailLogic) GetRoleDetail(req *types.GetRoleDetailReq) (resp *types.GetRoleDetailResp, err error) {
	// 使用MapReduceVoid并发获取角色信息和菜单ID
	var role *model.AdminRole
	var menuIds []string
	var mutex sync.Mutex
	var wg sync.WaitGroup

	mr.MapReduceVoid(func(source chan<- interface{}) {
		source <- 1 // 获取角色信息
		source <- 2 // 获取菜单ID
	}, func(item interface{}, writer mr.Writer[interface{}], cancel func(error)) {
		taskType := item.(int)
		wg.Add(1)
		defer wg.Done()

		if taskType == 1 {
			result, err := l.svcCtx.AdminRoleModel.FindOne(l.ctx, req.Id)
			if err != nil {
				cancel(err)
				return
			}
			mutex.Lock()
			role = result
			mutex.Unlock()
		} else if taskType == 2 {
			builder := l.svcCtx.AdminRoleMenuModel.SelectBuilder().
				Where("role_id = ?", req.Id)
			menus, err := l.svcCtx.AdminRoleMenuModel.FindAll(l.ctx, builder, "id ASC")
			if err != nil {
				cancel(err)
				return
			}
			mutex.Lock()
			menuIds = lo.Map(menus, func(item *model.AdminRoleMenu, _ int) string {
				return item.MenuId
			})
			mutex.Unlock()
		}
	}, func(pipe <-chan interface{}, cancel func(error)) {
		// 不需要处理pipe中的数据
	})

	wg.Wait()

	if role == nil {
		return nil, errors.Wrapf(xerr.NewErrMsg("角色不存在"), "获取角色详情失败, 角色不存在err: %v", err)
	}

	return &types.GetRoleDetailResp{
		Id:          role.Id,
		RoleName:    role.RoleName,
		RoleCode:    role.RoleCode,
		Description: role.Description,
		Status:      role.Status,
		Sort:        role.Sort,
		CreateTime:  role.CreateTime.Format("2006-01-02 15:04:05"),
		UpdateTime:  role.UpdateTime.Format("2006-01-02 15:04:05"),
		MenuIds:     menuIds,
	}, nil
}
