package logic

import (
	"context"
	"encoding/json"
	"errors"
	"juwan-backend/app/users/rpc/internal/models"
	"juwan-backend/app/users/rpc/internal/models/users"
	"juwan-backend/app/users/rpc/internal/svc"
	"juwan-backend/app/users/rpc/pb"

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

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

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

var SearUsersErr = errors.New("search users failed")

func (l *SearchUsersLogic) SearchUsers(in *pb.SearchUsersReq) (out *pb.SearchUsersResp, err error) {
	if in.Offset == nil || *in.Offset < 0 {
		zero := int64(0)
		in.Offset = &zero
	}
	if in.Limit == nil || *in.Limit <= 0 {
		def := int64(20)
		in.Limit = &def
	}
	if *in.Limit > 100 {
		return nil, errors.New("limit too large")
	}
	user, err := l.svcCtx.UsersModelRO.Users.Query().
		Where(users.Or(
			users.UsernameContainsFold(*in.Username),
			users.NicknameContainsFold(*in.Username),
			users.EmailContainsFold(*in.Username),
			users.CurrentRole(*in.CurrentRole),
		)).
		Offset(int(*in.Offset)).
		Limit(int(*in.Limit)).
		All(l.ctx)
	if err != nil {
		logx.Errorf("search users failed, err:%v.", err)
		return nil, SearUsersErr
	}
	out = &pb.SearchUsersResp{
		Users: ConvertEntUsersToProto(user),
	}

	return
}

func ConvertEntUserToProto(entUser *models.Users) *pb.Users {
	if entUser == nil {
		return nil
	}
	out := &pb.Users{}
	err := copier.Copy(out, entUser)
	if err != nil {
		return out
	}
	out.CreatedAt = entUser.CreatedAt.Unix()
	out.UpdatedAt = entUser.UpdatedAt.Unix()
	if !entUser.DeletedAt.IsZero() {
		out.DeletedAt = entUser.DeletedAt.Unix()
	}

	verificationStatus, err := json.Marshal(entUser.VerificationStatus)
	if err != nil {
		return nil
	}

	out.VerificationStatus = string(verificationStatus)
	//out.VerifiedRoles = entUser.VerifiedRoles
	out.VerifiedRoles = entUser.VerifiedRoles.Elements

	out.PasswordHash = "" // 手动清空敏感字段
	return out
}
func ConvertEntUsersToProto(users []*models.Users) []*pb.Users {
	list := make([]*pb.Users, 0, len(users))
	for _, u := range users {
		list = append(list, ConvertEntUserToProto(u))
	}
	return list
}
