package user

import (
	"context"
	"strings"

	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	invitedomain "hyapp/services/user-service/internal/domain/invite"
	userdomain "hyapp/services/user-service/internal/domain/user"
)

// SearchInviteReferrer 通过邀请码搜索可绑定邀请人。
// 邀请归因按 app 和区域隔离；国家只是用户资料快照，不能把同区域的跨国家邀请误判为不存在。
func (s *Service) SearchInviteReferrer(ctx context.Context, userID int64, inviteCode string) (userdomain.User, error) {
	inviteCode = invitedomain.NormalizeCode(inviteCode)
	if userID <= 0 {
		return userdomain.User{}, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if !invitedomain.ValidCode(inviteCode) {
		// 对外搜索入口只接受合法邀请码；非法输入直接拒绝，不落入 NotFound 分支。
		return userdomain.User{}, xerr.New(xerr.InvalidInviteCode, "invalid invite code")
	}
	if s.userRepository == nil {
		return userdomain.User{}, xerr.New(xerr.Unavailable, "user repository is not configured")
	}

	current, err := s.userRepository.GetUser(ctx, userID)
	if err != nil {
		return userdomain.User{}, err
	}
	if !current.ProfileCompleted {
		// H5 绑定入口只服务已完成资料用户；注册资料页绑定走 CompleteOnboarding 的原子写链路。
		return userdomain.User{}, xerr.New(xerr.ProfileRequired, "profile required")
	}

	inviter, err := s.userRepository.FindInviteReferrerByCode(ctx, appcode.FromContext(ctx), inviteCode)
	if err != nil {
		return userdomain.User{}, err
	}
	if err := validateInviteReferrerPair(current, inviter); err != nil {
		return userdomain.User{}, err
	}

	return s.refreshExpiredUser(ctx, inviter, "")
}

// BindInviteReferrer 原子绑定当前用户的邀请人。
// H5 只能传用户输入的邀请码；归属用户由 repository 在事务内重新解析并复核。
func (s *Service) BindInviteReferrer(ctx context.Context, userID int64, inviteCode string, requestID string) (userdomain.User, error) {
	inviteCode = invitedomain.NormalizeCode(inviteCode)
	if userID <= 0 {
		return userdomain.User{}, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if !invitedomain.ValidCode(inviteCode) {
		return userdomain.User{}, xerr.New(xerr.InvalidInviteCode, "invalid invite code")
	}
	if s.userRepository == nil {
		return userdomain.User{}, xerr.New(xerr.Unavailable, "user repository is not configured")
	}

	return s.userRepository.BindInviteReferrer(ctx, userdomain.BindInviteReferrerCommand{
		AppCode:       appcode.FromContext(ctx),
		InvitedUserID: userID,
		InviteCode:    inviteCode,
		RequestID:     strings.TrimSpace(requestID),
		BoundAtMs:     s.now().UnixMilli(),
	})
}

func validateInviteReferrerPair(invited userdomain.User, inviter userdomain.User) error {
	if invited.UserID <= 0 || inviter.UserID <= 0 {
		return xerr.New(xerr.NotFound, "inviter not found")
	}
	if invited.UserID == inviter.UserID {
		// 自邀不进入邀请码解析，避免把当前用户自己的邀请码可用性暴露出去。
		return xerr.New(xerr.InvalidInviteCode, "invalid invite code")
	}
	if !inviter.ProfileCompleted || !inviter.CanLogin() {
		return xerr.New(xerr.NotFound, "inviter not found")
	}
	if invited.RegionID != inviter.RegionID {
		// 产品边界是同区域邀请；跨区域统一按未找到处理，避免 H5 用搜索接口枚举其他区域用户。
		return xerr.New(xerr.NotFound, "inviter not found")
	}
	return nil
}
