package admin_user

import (
	"context"
	"sync"

	"ycc-server/app/main/api/internal/svc"
	"ycc-server/app/main/api/internal/types"
	"ycc-server/app/main/model"

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

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

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

func (l *AdminGetUserListLogic) AdminGetUserList(req *types.AdminGetUserListReq) (resp *types.AdminGetUserListResp, err error) {
	resp = &types.AdminGetUserListResp{
		Items: make([]types.AdminUserListItem, 0),
		Total: 0,
	}

	// 构建查询条件
	builder := l.svcCtx.AdminUserModel.SelectBuilder().
		Where("del_state = ?", 0)
	if len(req.Username) > 0 {
		builder = builder.Where("username LIKE ?", "%"+req.Username+"%")
	}
	if len(req.RealName) > 0 {
		builder = builder.Where("real_name LIKE ?", "%"+req.RealName+"%")
	}
	if req.Status != -1 {
		builder = builder.Where("status = ?", req.Status)
	}

	// 设置分页
	offset := (req.Page - 1) * req.PageSize
	builder = builder.OrderBy("id DESC").Limit(uint64(req.PageSize)).Offset(uint64(offset))

	// 使用MapReduceVoid并发获取总数和列表数据
	var users []*model.AdminUser
	var total int64
	var mutex sync.Mutex
	var wg sync.WaitGroup

	mr.MapReduceVoid(func(source chan<- interface{}) {
		source <- 1 // 获取用户列表
		source <- 2 // 获取总数
	}, func(item interface{}, writer mr.Writer[*model.AdminUser], cancel func(error)) {
		taskType := item.(int)
		wg.Add(1)
		defer wg.Done()

		if taskType == 1 {
			result, err := l.svcCtx.AdminUserModel.FindAll(l.ctx, builder, "id DESC")
			if err != nil {
				cancel(err)
				return
			}
			mutex.Lock()
			users = result
			mutex.Unlock()
		} else if taskType == 2 {
			countBuilder := l.svcCtx.AdminUserModel.SelectBuilder().
				Where("del_state = ?", 0)
			if len(req.Username) > 0 {
				countBuilder = countBuilder.Where("username LIKE ?", "%"+req.Username+"%")
			}
			if len(req.RealName) > 0 {
				countBuilder = countBuilder.Where("real_name LIKE ?", "%"+req.RealName+"%")
			}
			if req.Status != -1 {
				countBuilder = countBuilder.Where("status = ?", req.Status)
			}

			count, err := l.svcCtx.AdminUserModel.FindCount(l.ctx, countBuilder, "id")
			if err != nil {
				cancel(err)
				return
			}
			mutex.Lock()
			total = count
			mutex.Unlock()
		}
	}, func(pipe <-chan *model.AdminUser, cancel func(error)) {
		// 不需要处理pipe中的数据
	})

	wg.Wait()

	// 并发获取每个用户的角色ID
	var userItems []types.AdminUserListItem
	var userItemsMutex sync.Mutex

	mr.MapReduceVoid(func(source chan<- interface{}) {
		for _, user := range users {
			source <- user
		}
	}, func(item interface{}, writer mr.Writer[[]int64], cancel func(error)) {
		user := item.(*model.AdminUser)

		// 获取用户关联的角色ID
		builder := l.svcCtx.AdminUserRoleModel.SelectBuilder().
			Where("user_id = ?", user.Id)
		roles, err := l.svcCtx.AdminUserRoleModel.FindAll(l.ctx, builder, "id ASC")
		if err != nil {
			cancel(err)
			return
		}
		roleIds := lo.Map(roles, func(item *model.AdminUserRole, _ int) int64 {
			return item.RoleId
		})

		writer.Write(roleIds)
	}, func(pipe <-chan []int64, cancel func(error)) {
		for _, user := range users {
			roleIds := <-pipe
			item := types.AdminUserListItem{
				Id:         user.Id,
				Username:   user.Username,
				RealName:   user.RealName,
				Status:     user.Status,
				CreateTime: user.CreateTime.Format("2006-01-02 15:04:05"),
				RoleIds:    roleIds,
			}
			userItemsMutex.Lock()
			userItems = append(userItems, item)
			userItemsMutex.Unlock()
		}
	})

	resp.Items = userItems
	resp.Total = total

	return resp, nil
}
