package benefactorservice

import (
	"context"

	"git.gocasts.ir/ebhomengo/niki/entity"
	benefactoreparam "git.gocasts.ir/ebhomengo/niki/param/benefactor/benefactor"
	errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
	richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
)

func (s Service) LoginOrRegister(ctx context.Context, req benefactoreparam.LoginOrRegisterRequest) (benefactoreparam.LoginOrRegisterResponse, error) {
	const op = "benefactorservice.LoginOrRegister"
	if fieldErrors, vErr := s.vld.ValidateLoginRegisterRequest(req); vErr != nil {
		return benefactoreparam.LoginOrRegisterResponse{FieldErrors: fieldErrors}, richerror.New(op).WithErr(vErr)
	}
	code, gErr := s.redisOtp.GetCodeByPhoneNumber(ctx, req.PhoneNumber)
	if gErr != nil {
		return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(gErr).WithKind(richerror.KindUnexpected)
	}
	if code == "" || code != req.VerificationCode {
		return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithMessage(errmsg.ErrorMsgOtpCodeIsNotValid).WithKind(richerror.KindForbidden)
	}

	_, dErr := s.redisOtp.DeleteCodeByPhoneNumber(ctx, req.PhoneNumber)
	if dErr != nil {
		return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(dErr).WithKind(richerror.KindUnexpected)
	}

	isExist, benefactor, rErr := s.repo.IsExistBenefactorByPhoneNumber(ctx, req.PhoneNumber)
	if rErr != nil {
		return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(rErr).WithKind(richerror.KindUnexpected)
	}
	if !isExist {
		newBenefactor, err := s.repo.CreateBenefactor(ctx, entity.Benefactor{
			PhoneNumber: req.PhoneNumber,
			Role:        entity.UserBenefactorRole,
		})
		if err != nil {
			return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(err).WithKind(richerror.KindUnexpected)
		}

		benefactor = newBenefactor
	}

	athenticableBenefactor := entity.Authenticable{
		ID:   benefactor.ID,
		Role: entity.UserBenefactorRole.String(),
	}
	accessToken, aErr := s.auth.CreateAccessToken(athenticableBenefactor)
	if aErr != nil {
		return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(aErr).WithKind(richerror.KindUnexpected)
	}

	refreshToken, rErr := s.auth.CreateRefreshToken(athenticableBenefactor)
	if rErr != nil {
		return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(rErr).WithKind(richerror.KindUnexpected)
	}

	return benefactoreparam.LoginOrRegisterResponse{
		Data: benefactoreparam.Data{
			ID:        benefactor.ID,
			FirstName: benefactor.FirstName,
			LastName:  benefactor.LastName,
			Role:      entity.UserBenefactorRole,
		},
		Tokens: benefactoreparam.Tokens{
			AccessToken:  accessToken,
			RefreshToken: refreshToken,
		},
	}, nil
}
