package logic

import (
	"context"
	"encoding/json"
	"errors"
	"juwan-backend/app/user_verifications/rpc/internal/models/schema"

	"juwan-backend/app/user_verifications/rpc/internal/svc"
	"juwan-backend/app/user_verifications/rpc/pb"
	userspb "juwan-backend/app/users/rpc/pb"
	"slices"

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

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

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

func (l *UpdateUserVerificationsLogic) UpdateUserVerifications(in *pb.UpdateUserVerificationsReq) (*pb.UpdateUserVerificationsResp, error) {
	var materials *schema.MaterialStruct
	materials = nil
	if in.Materials != nil {
		err := json.Unmarshal([]byte(*in.Materials), &materials)
		if err != nil {
			logx.Errorf("Unmarshal materials failed, err:%v.", err)
			return nil, errors.New("bad input materials")
		}
		if len(materials.GameScreenshots) > 20 {
			logx.Errorf("User %v upload oo many game screenshots: %d", in.UserId, len(materials.GameScreenshots))
			return nil, errors.New("too many game screenshots")
		}
	}

	uv, err := l.svcCtx.UserVeriModelRW.UpdateOneID(in.Id).
		SetNillableRejectReason(in.RejectReason).
		SetNillableMaterials(materials).
		SetNillableRole(in.Role).
		SetNillableStatus(in.Status).
		SetReviewedBy(in.ReviewedBy).
		Save(l.ctx)
	if err != nil {
		logx.Errorf("save user verifications failed, err:%v.", err)
		return nil, errors.New("save user verifications failed")
	}

	if in.Status != nil && *in.Status == "approved" && uv.Role != "" {
		userResp, err := l.svcCtx.UserRpc.GetUsersById(l.ctx, &userspb.GetUsersByIdReq{Id: uv.UserID})
		if err != nil {
			logx.Errorf("get user by id failed when syncing verified roles, err:%v.", err)
			return nil, errors.New("sync verified roles failed")
		}

		verifiedRoles := append([]string{}, userResp.Users.VerifiedRoles...)
		if !slices.Contains(verifiedRoles, uv.Role) {
			verifiedRoles = append(verifiedRoles, uv.Role)
			_, err = l.svcCtx.UserRpc.UpdateUsers(l.ctx, &userspb.UpdateUsersReq{
				Id:            uv.UserID,
				VerifiedRoles: verifiedRoles,
			})
			if err != nil {
				logx.Errorf("update user verified roles failed, err:%v.", err)
				return nil, errors.New("sync verified roles failed")
			}
		}
	}

	return &pb.UpdateUserVerificationsResp{}, nil
}
