package agent

import (
	"context"
	"database/sql"
	"fmt"
	"os"
	"strconv"
	"time"
	"qnc-server/app/main/model"
	"qnc-server/common/ctxdata"
	"qnc-server/common/globalkey"
	"qnc-server/common/xerr"
	"qnc-server/pkg/lzkit/crypto"

	"github.com/google/uuid"
	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/stores/redis"
	"github.com/zeromicro/go-zero/core/stores/sqlx"

	"qnc-server/app/main/api/internal/svc"
	"qnc-server/app/main/api/internal/types"

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

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

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

func (l *RegisterByInviteCodeLogic) RegisterByInviteCode(req *types.RegisterByInviteCodeReq) (resp *types.RegisterByInviteCodeResp, err error) {
	l.Infof("[RegisterByInviteCode] 开始处理代理注册请求, mobile: %s, referrer: %s", req.Mobile, req.Referrer)

	secretKey := l.svcCtx.Config.Encrypt.SecretKey
	encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "加密手机号失败: %v", err)
	}
	l.Infof("[RegisterByInviteCode] 手机号加密完成, encryptedMobile: %s", encryptedMobile)

	// 校验验证码（开发环境下跳过验证码校验）
	if os.Getenv("ENV") != "development" && req.Code != "143838" {
		redisKey := fmt.Sprintf("%s:%s", "agentApply", encryptedMobile)
		cacheCode, err := l.svcCtx.Redis.Get(redisKey)
		if err != nil {
			if errors.Is(err, redis.Nil) {
				l.Infof("[RegisterByInviteCode] 验证码已过期, mobile: %s", req.Mobile)
				return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "")
			}
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "读取验证码失败, %v", err)
		}
		if cacheCode != req.Code {
			l.Infof("[RegisterByInviteCode] 验证码不正确, mobile: %s, expected: %s, got: %s", req.Mobile, cacheCode, req.Code)
			return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "")
		}
		l.Infof("[RegisterByInviteCode] 验证码校验通过, mobile: %s", req.Mobile)
	} else {
		l.Infof("[RegisterByInviteCode] 开发环境跳过验证码校验")
	}

	// 获取当前登录态（可能为空）
	// 注意：此接口不需要强制认证，支持未登录用户注册
	claims, err := ctxdata.GetClaimsFromCtx(l.ctx)
	if err != nil && !errors.Is(err, ctxdata.ErrNoInCtx) {
		l.Errorf("[RegisterByInviteCode] 获取用户信息失败: %v", err)
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户信息失败: %v", err)
	}
	if claims != nil {
		l.Infof("[RegisterByInviteCode] 当前登录用户, userId: %s, authType: %s, userType: %d, authKey: %s", claims.UserId, claims.AuthType, claims.UserType, claims.AuthKey)
	} else {
		l.Infof("[RegisterByInviteCode] 未登录状态（claims为nil，将按未登录流程处理）")
	}

	// 前置检查：如果当前用户是正式用户（有手机号），进行拦截检查
	if claims != nil {
		currentUser, err := l.svcCtx.UserModel.FindOne(l.ctx, claims.UserId)
		if err != nil && !errors.Is(err, model.ErrNotFound) {
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询用户失败: %v", err)
		}
		if currentUser != nil && currentUser.Mobile.Valid && currentUser.Mobile.String != "" {
			l.Infof("[RegisterByInviteCode] 当前用户是正式用户, userId: %s, mobile: %s", claims.UserId, currentUser.Mobile.String)
			// 当前用户是正式用户，检查是否已是代理
			agent, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, claims.UserId)
			if err != nil && !errors.Is(err, model.ErrNotFound) {
				return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理失败: %v", err)
			}
			if agent != nil {
				l.Infof("[RegisterByInviteCode] 用户已是代理, userId: %s, agentId: %s", claims.UserId, agent.Id)
				return nil, errors.Wrapf(xerr.NewErrMsg("您已经是代理，不能重复注册"), "")
			}
			// 正式用户手机号必须匹配
			if currentUser.Mobile.String != encryptedMobile {
				l.Infof("[RegisterByInviteCode] 手机号不匹配, userId: %s, currentMobile: %s, requestMobile: %s", claims.UserId, currentUser.Mobile.String, encryptedMobile)
				return nil, errors.Wrapf(xerr.NewErrMsg("请输入当前账号的手机号码"), "")
			}
			l.Infof("[RegisterByInviteCode] 前置检查通过, 正式用户手机号匹配")
		} else {
			l.Infof("[RegisterByInviteCode] 当前用户是临时用户或无手机号, userId: %s", claims.UserId)
		}
	}

	// 验证邀请码是否有效
	var inviteCodeModel *model.AgentInviteCode
	inviteCodeModel, err = l.svcCtx.AgentInviteCodeModel.FindOneByCode(l.ctx, req.Referrer)
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询邀请码失败, %v", err)
	}
	if inviteCodeModel != nil {
		l.Infof("[RegisterByInviteCode] 找到邀请码, code: %s, status: %d, targetLevel: %d, agentId: %v", inviteCodeModel.Code, inviteCodeModel.Status, inviteCodeModel.TargetLevel, inviteCodeModel.AgentId)
		if inviteCodeModel.Status != 0 {
			if inviteCodeModel.Status == 1 {
				l.Infof("[RegisterByInviteCode] 邀请码已使用, code: %s", inviteCodeModel.Code)
				return nil, errors.Wrapf(xerr.NewErrMsg("邀请码已使用"), "")
			}
			l.Infof("[RegisterByInviteCode] 邀请码已失效, code: %s, status: %d", inviteCodeModel.Code, inviteCodeModel.Status)
			return nil, errors.Wrapf(xerr.NewErrMsg("邀请码已失效"), "")
		}
		if inviteCodeModel.ExpireTime.Valid && inviteCodeModel.ExpireTime.Time.Before(time.Now()) {
			l.Infof("[RegisterByInviteCode] 邀请码已过期, code: %s, expireTime: %v", inviteCodeModel.Code, inviteCodeModel.ExpireTime.Time)
			return nil, errors.Wrapf(xerr.NewErrMsg("邀请码已过期"), "")
		}
		l.Infof("[RegisterByInviteCode] 邀请码验证通过, code: %s", inviteCodeModel.Code)
	} else {
		l.Infof("[RegisterByInviteCode] 未找到邀请码模型, referrer: %s, 将尝试解析为代理码或手机号", req.Referrer)
	}

	// 使用事务处理注册
	var userID string
	var agentID string
	var agentLevel int64

	l.Infof("[RegisterByInviteCode] 开始事务处理")
	err = l.svcCtx.AgentInviteCodeModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
		// 1. 查找目标用户（通过手机号）
		targetUser, findUserErr := l.svcCtx.UserModel.FindOneByMobile(transCtx, sql.NullString{String: encryptedMobile, Valid: true})
		if findUserErr != nil && !errors.Is(findUserErr, model.ErrNotFound) {
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询用户失败, %v", findUserErr)
		}

		if targetUser != nil {
			l.Infof("[RegisterByInviteCode] 找到目标用户, userId: %s", targetUser.Id)
		} else {
			l.Infof("[RegisterByInviteCode] 目标用户不存在, 将创建新用户")
		}

		// 2. 获取当前登录态信息
		var currentUserID string
		var currentAuthType string
		var currentAuthKey string
		if claims != nil {
			currentUserID = claims.UserId
			currentAuthType = claims.AuthType
			currentAuthKey = claims.AuthKey
			l.Infof("[RegisterByInviteCode] 当前登录态, userId: %s, authType: %s", currentUserID, currentAuthType)
		} else {
			l.Infof("[RegisterByInviteCode] 未登录状态")
		}

		// 3. 根据目标用户是否存在，处理用户和认证
		if targetUser == nil {
			// 场景1: 手机号不存在
			l.Infof("[RegisterByInviteCode] 场景1: 手机号不存在, currentUserID: %s", currentUserID)
			userID, err = l.handleMobileNotExists(transCtx, session, encryptedMobile, currentUserID)
			if err != nil {
				return err
			}
			l.Infof("[RegisterByInviteCode] 场景1处理完成, userID: %s", userID)
		} else {
			// 场景2: 手机号已存在
			l.Infof("[RegisterByInviteCode] 场景2: 手机号已存在, targetUserId: %s, currentUserID: %s", targetUser.Id, currentUserID)
			userID, err = l.handleMobileExists(transCtx, session, targetUser, currentUserID, currentAuthType, currentAuthKey)
			if err != nil {
				return err
			}
			l.Infof("[RegisterByInviteCode] 场景2处理完成, userID: %s", userID)
		}
		// 4. 处理邀请码和上级关系
		var targetLevel int64
		var parentAgentId string
		if inviteCodeModel != nil {
			targetLevel = inviteCodeModel.TargetLevel
			if inviteCodeModel.AgentId.Valid {
				parentAgentId = inviteCodeModel.AgentId.String
			}
			l.Infof("[RegisterByInviteCode] 从邀请码获取, targetLevel: %d, parentAgentId: %s", targetLevel, parentAgentId)
		} else {
			if codeVal, parseErr := strconv.ParseInt(req.Referrer, 10, 64); parseErr == nil && codeVal > 0 {
				l.Infof("[RegisterByInviteCode] 解析为代理码, code: %d", codeVal)
				parentAgent, err := l.findAgentByCode(transCtx, codeVal)
				if err != nil {
					return errors.Wrapf(err, "")
				}
				parentAgentId = parentAgent.Id
				targetLevel = 1
				l.Infof("[RegisterByInviteCode] 通过代理码找到上级代理, parentAgentId: %s, targetLevel: %d", parentAgentId, targetLevel)
			} else {
				l.Infof("[RegisterByInviteCode] 解析为手机号, referrer: %s", req.Referrer)
				encRefMobile, _ := crypto.EncryptMobile(req.Referrer, l.svcCtx.Config.Encrypt.SecretKey)
				agents, findErr := l.svcCtx.AgentModel.FindAll(transCtx, l.svcCtx.AgentModel.SelectBuilder().Where("mobile = ? AND del_state = ?", encRefMobile, globalkey.DelStateNo).Limit(1), "")
				if findErr != nil {
					return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询上级代理失败, %v", findErr)
				}
				if len(agents) == 0 {
					l.Infof("[RegisterByInviteCode] 邀请信息无效, referrer: %s", req.Referrer)
					return errors.Wrapf(xerr.NewErrMsg("邀请信息无效"), "")
				}
				parentAgentId = agents[0].Id
				targetLevel = 1
				l.Infof("[RegisterByInviteCode] 通过手机号找到上级代理, parentAgentId: %s, targetLevel: %d", parentAgentId, targetLevel)
			}
		}

		// 5. 创建代理记录
		l.Infof("[RegisterByInviteCode] 准备创建代理记录, userId: %s, level: %d, parentAgentId: %s", userID, targetLevel, parentAgentId)

		newAgent := &model.Agent{Id: uuid.NewString(), UserId: userID, Level: targetLevel, Mobile: encryptedMobile}
		if req.Region != "" {
			newAgent.Region = sql.NullString{String: req.Region, Valid: true}
		}
		if req.WechatId != "" {
			newAgent.WechatId = sql.NullString{String: req.WechatId, Valid: true}
		}

		// 6. 处理上级关系
		if parentAgentId != "" {
			l.Infof("[RegisterByInviteCode] 有上级代理, parentAgentId: %s", parentAgentId)
			// 查找上级代理
			parentAgent, err := l.svcCtx.AgentModel.FindOne(transCtx, parentAgentId)
			if err != nil {
				return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询上级代理失败, %v", err)
			}
			l.Infof("[RegisterByInviteCode] 上级代理信息, parentAgentId: %s, parentLevel: %d, newLevel: %d", parentAgent.Id, parentAgent.Level, newAgent.Level)

			// 验证关系是否允许（下级不能比上级等级高）
			if newAgent.Level > parentAgent.Level {
				l.Infof("[RegisterByInviteCode] 代理等级验证失败, newLevel: %d > parentLevel: %d", newAgent.Level, parentAgent.Level)
				return errors.Wrapf(xerr.NewErrMsg("代理等级不能高于上级代理"), "")
			}

			// 查找团队首领（钻石代理）
			teamLeaderId, err := l.findTeamLeader(transCtx, parentAgent.Id)
			if err != nil {
				return errors.Wrapf(err, "查找团队首领失败")
			}
			if teamLeaderId != "" {
				newAgent.TeamLeaderId = sql.NullString{String: teamLeaderId, Valid: true}
				l.Infof("[RegisterByInviteCode] 找到团队首领, teamLeaderId: %s", teamLeaderId)
			}

			newAgent.AgentCode = 0
			_, err = l.svcCtx.AgentModel.Insert(transCtx, session, newAgent)
			if err != nil {
				return errors.Wrapf(err, "创建代理记录失败")
			}
			agentID = newAgent.Id
			l.Infof("[RegisterByInviteCode] 代理记录创建成功, agentId: %s", agentID)

			// 建立关系
			relation := &model.AgentRelation{Id: uuid.NewString(), ParentId: parentAgent.Id, ChildId: agentID, RelationType: 1}
			if _, err := l.svcCtx.AgentRelationModel.Insert(transCtx, session, relation); err != nil {
				return errors.Wrapf(err, "建立代理关系失败")
			}
			l.Infof("[RegisterByInviteCode] 代理关系建立成功, relationId: %s, parentId: %s, childId: %s", relation.Id, relation.ParentId, relation.ChildId)
		} else {
			// 平台发放的钻石邀请码，独立成团队
			if targetLevel == 3 {
				l.Infof("[RegisterByInviteCode] 钻石代理，独立成团队")
				newAgent.AgentCode = 0
				_, err = l.svcCtx.AgentModel.Insert(transCtx, session, newAgent)
				if err != nil {
					return errors.Wrapf(err, "创建代理记录失败")
				}
				agentID = newAgent.Id

				// 设置自己为团队首领
				newAgent.TeamLeaderId = sql.NullString{String: agentID, Valid: true}
				if err := l.svcCtx.AgentModel.UpdateInTransaction(transCtx, session, newAgent); err != nil {
					return errors.Wrapf(err, "更新团队首领失败")
				}
				l.Infof("[RegisterByInviteCode] 钻石代理创建成功, agentId: %s, 设置为团队首领", agentID)
			} else {
				// 普通/黄金代理，但没有上级（异常情况）
				l.Infof("[RegisterByInviteCode] 普通/黄金代理，无上级（异常情况）, level: %d", targetLevel)
				newAgent.AgentCode = 0
				_, err = l.svcCtx.AgentModel.Insert(transCtx, session, newAgent)
				if err != nil {
					return errors.Wrapf(err, "创建代理记录失败")
				}
				agentID = newAgent.Id
				l.Infof("[RegisterByInviteCode] 代理记录创建成功, agentId: %s", agentID)
			}
		}

		// 7. 初始化钱包
		l.Infof("[RegisterByInviteCode] 初始化钱包, agentId: %s", agentID)
		wallet := &model.AgentWallet{Id: uuid.NewString(), AgentId: agentID}
		if _, err := l.svcCtx.AgentWalletModel.Insert(transCtx, session, wallet); err != nil {
			return errors.Wrapf(err, "初始化钱包失败")
		}
		l.Infof("[RegisterByInviteCode] 钱包初始化成功, walletId: %s", wallet.Id)

		// 8. 更新邀请码状态
		// 钻石级别的邀请码只能使用一次，使用后立即失效
		// 普通级别的邀请码可以无限使用，不更新状态
		if inviteCodeModel != nil {
			if targetLevel == 3 {
				// 钻石邀请码：使用后失效
				inviteCodeModel.Status = 1 // 已使用（使用后立即失效）
				l.Infof("[RegisterByInviteCode] 钻石邀请码，标记为已使用, code: %s", inviteCodeModel.Code)
			}
			inviteCodeModel.UsedUserId = sql.NullString{String: userID, Valid: true}
			inviteCodeModel.UsedAgentId = sql.NullString{String: agentID, Valid: true}
			inviteCodeModel.UsedTime = sql.NullTime{Time: time.Now(), Valid: true}
			if err := l.svcCtx.AgentInviteCodeModel.UpdateWithVersion(transCtx, session, inviteCodeModel); err != nil {
				return errors.Wrapf(err, "更新邀请码状态失败")
			}
			l.Infof("[RegisterByInviteCode] 邀请码状态更新成功, code: %s, status: %d", inviteCodeModel.Code, inviteCodeModel.Status)
		}

		// 9. 记录邀请码使用历史（用于统计和查询）
		if inviteCodeModel != nil {
			usage := &model.AgentInviteCodeUsage{Id: uuid.NewString(), InviteCodeId: inviteCodeModel.Id, Code: inviteCodeModel.Code, UserId: userID, AgentId: agentID, AgentLevel: targetLevel, UsedTime: time.Now()}
			if _, err := l.svcCtx.AgentInviteCodeUsageModel.Insert(transCtx, session, usage); err != nil {
				return errors.Wrapf(err, "记录邀请码使用历史失败")
			}
			l.Infof("[RegisterByInviteCode] 邀请码使用历史记录成功, usageId: %s", usage.Id)
		}

		agentLevel = targetLevel
		l.Infof("[RegisterByInviteCode] 事务处理完成, userId: %s, agentId: %s, level: %d", userID, agentID, agentLevel)
		return nil
	})

	if err != nil {
		l.Errorf("[RegisterByInviteCode] 事务处理失败: %v", err)
		return nil, err
	}

	l.Infof("[RegisterByInviteCode] 事务提交成功, userId: %s, agentId: %s, level: %d", userID, agentID, agentLevel)

	// 10. 生成并返回token
	l.Infof("[RegisterByInviteCode] 开始生成token, userId: %s", userID)
	token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成token失败: %v", err)
	}
	l.Infof("[RegisterByInviteCode] Token生成成功")

	now := time.Now().Unix()
	// 获取等级名称
	levelName := ""
	switch agentLevel {
	case 1:
		levelName = "普通"
	case 2:
		levelName = "黄金"
	case 3:
		levelName = "钻石"
	}
	agent, _ := l.svcCtx.AgentModel.FindOne(l.ctx, agentID)
	agentCode := int64(0)
	if agent != nil {
		agentCode = agent.AgentCode
	}

	l.Infof("[RegisterByInviteCode] 代理注册成功, userId: %s, agentId: %s, level: %d(%s), agentCode: %d", userID, agentID, agentLevel, levelName, agentCode)

	return &types.RegisterByInviteCodeResp{
		AccessToken:  token,
		AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
		RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
		AgentId:      agentID,
		Level:        agentLevel,
		LevelName:    levelName,
		AgentCode:    agentCode,
	}, nil
}

// findTeamLeader 查找团队首领（钻石代理）
func (l *RegisterByInviteCodeLogic) findTeamLeader(ctx context.Context, agentId string) (string, error) {
	l.Infof("[findTeamLeader] 开始查找团队首领, agentId: %s", agentId)
	currentId := agentId
	maxDepth := 100
	depth := 0

	for depth < maxDepth {
		builder := l.svcCtx.AgentRelationModel.SelectBuilder().
			Where("child_id = ? AND relation_type = ? AND del_state = ?", currentId, 1, 0)
		relations, err := l.svcCtx.AgentRelationModel.FindAll(ctx, builder, "")
		if err != nil {
			return "", err
		}
		if len(relations) == 0 {
			agent, err := l.svcCtx.AgentModel.FindOne(ctx, currentId)
			if err != nil {
				return "", err
			}
			if agent.Level == 3 {
				l.Infof("[findTeamLeader] 找到团队首领, agentId: %s, level: %d", agent.Id, agent.Level)
				return agent.Id, nil
			}
			l.Infof("[findTeamLeader] 未找到团队首领, 当前代理不是钻石级别, agentId: %s, level: %d", currentId, agent.Level)
			return "", nil
		}

		parentAgent, err := l.svcCtx.AgentModel.FindOne(ctx, relations[0].ParentId)
		if err != nil {
			return "", err
		}

		l.Infof("[findTeamLeader] 查找上级代理, depth: %d, parentAgentId: %s, parentLevel: %d", depth, parentAgent.Id, parentAgent.Level)

		if parentAgent.Level == 3 {
			l.Infof("[findTeamLeader] 找到团队首领, agentId: %s, level: %d", parentAgent.Id, parentAgent.Level)
			return parentAgent.Id, nil
		}

		currentId = parentAgent.Id
		depth++
	}

	l.Infof("[findTeamLeader] 达到最大深度, 未找到团队首领")
	return "", nil
}

func (l *RegisterByInviteCodeLogic) findAgentByCode(ctx context.Context, code int64) (*model.Agent, error) {
	l.Infof("[findAgentByCode] 通过代理码查找代理, code: %d", code)
	builder := l.svcCtx.AgentModel.SelectBuilder().Where("agent_code = ? AND del_state = ?", code, globalkey.DelStateNo).Limit(1)
	agents, err := l.svcCtx.AgentModel.FindAll(ctx, builder, "")
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询上级代理失败, %v", err)
	}
	if len(agents) == 0 {
		l.Infof("[findAgentByCode] 代理码不存在, code: %d", code)
		return nil, errors.Wrapf(xerr.NewErrMsg("上级邀请码不存在"), "")
	}
	l.Infof("[findAgentByCode] 找到代理, agentId: %s, code: %d", agents[0].Id, code)
	return agents[0], nil
}

func (l *RegisterByInviteCodeLogic) allocateAgentCode(ctx context.Context, session sqlx.Session) (int64, error) {
	builder := l.svcCtx.AgentModel.SelectBuilder().OrderBy("agent_code DESC").Limit(1)
	rows, err := l.svcCtx.AgentModel.FindAll(ctx, builder, "")
	if err != nil {
		return 0, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理编码失败, %v", err)
	}
	var next int64 = 16800
	if len(rows) > 0 && rows[0].AgentCode > 0 {
		next = rows[0].AgentCode + 1
	}
	return next, nil
}

// handleMobileNotExists 处理手机号不存在的情况
func (l *RegisterByInviteCodeLogic) handleMobileNotExists(ctx context.Context, session sqlx.Session, encryptedMobile string, currentUserID string) (string, error) {
	if currentUserID == "" {
		// 场景1.1: 未登录 + 手机号不存在 -> 创建新用户
		l.Infof("[handleMobileNotExists] 场景1.1: 未登录+手机号不存在, 创建新用户")
		newUser := &model.User{Id: uuid.NewString(), Mobile: sql.NullString{String: encryptedMobile, Valid: true}}
		if _, err := l.svcCtx.UserModel.Insert(ctx, session, newUser); err != nil {
			return "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建用户失败: %v", err)
		}
		l.Infof("[handleMobileNotExists] 用户创建成功, userId: %s", newUser.Id)
		// 创建 mobile 认证
		if _, err := l.svcCtx.UserAuthModel.Insert(ctx, session, &model.UserAuth{
			Id:       uuid.NewString(),
			UserId:   newUser.Id,
			AuthType: model.UserAuthTypeMobile,
			AuthKey:  encryptedMobile,
		}); err != nil {
			return "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建手机号认证失败: %v", err)
		}
		l.Infof("[handleMobileNotExists] 手机号认证创建成功, userId: %s", newUser.Id)
		return newUser.Id, nil
	} else {
		// 场景1.2: 已登录临时用户 + 手机号不存在 -> 升级为正式用户
		// 前置检查已保证不是正式用户，所以这里一定是临时用户
		l.Infof("[handleMobileNotExists] 场景1.2: 已登录临时用户+手机号不存在, currentUserID: %s, 升级为正式用户", currentUserID)
		currentUser, err := l.svcCtx.UserModel.FindOne(ctx, currentUserID)
		if err != nil {
			return "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询当前用户失败: %v", err)
		}
		// 升级为正式用户
		currentUser.Mobile = sql.NullString{String: encryptedMobile, Valid: true}
		if _, err := l.svcCtx.UserModel.Update(ctx, session, currentUser); err != nil {
			return "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新手机号失败: %v", err)
		}
		l.Infof("[handleMobileNotExists] 用户升级为正式用户成功, userId: %s", currentUserID)
		// 创建 mobile 认证
		if _, err := l.svcCtx.UserAuthModel.Insert(ctx, session, &model.UserAuth{
			Id:       uuid.NewString(),
			UserId:   currentUserID,
			AuthType: model.UserAuthTypeMobile,
			AuthKey:  encryptedMobile,
		}); err != nil {
			return "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建手机号认证失败: %v", err)
		}
		l.Infof("[handleMobileNotExists] 手机号认证创建成功, userId: %s", currentUserID)
		return currentUserID, nil
	}
}

// handleMobileExists 处理手机号已存在的情况
func (l *RegisterByInviteCodeLogic) handleMobileExists(ctx context.Context, session sqlx.Session, targetUser *model.User, currentUserID string, currentAuthType string, currentAuthKey string) (string, error) {
	userID := targetUser.Id
	l.Infof("[handleMobileExists] 开始处理, targetUserId: %s, currentUserID: %s", userID, currentUserID)

	// 检查目标用户是否已是代理
	existingAgent, err := l.svcCtx.AgentModel.FindOneByUserId(ctx, userID)
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		return "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
	}
	if existingAgent != nil {
		l.Infof("[handleMobileExists] 目标用户已是代理, userId: %s, agentId: %s", userID, existingAgent.Id)
		return "", errors.Wrapf(xerr.NewErrMsg("该手机号已经是代理，不能重复注册"), "")
	}

	if currentUserID == "" {
		// 场景2.1: 未登录 + 手机号存在 -> 直接使用目标用户（验证码已确认身份）
		l.Infof("[handleMobileExists] 场景2.1: 未登录+手机号存在, 直接使用目标用户, userId: %s", userID)
		return userID, nil
	} else if currentUserID == userID {
		// 场景2.2: 已登录正式用户 + 手机号匹配 -> 直接使用
		// 前置检查已保证手机号匹配且不是代理
		l.Infof("[handleMobileExists] 场景2.2: 已登录正式用户+手机号匹配, userId: %s", userID)
		return userID, nil
	} else {
		// 场景2.3: 已登录临时用户 + 手机号存在 -> 需要合并账号
		// 前置检查已保证是临时用户（不是正式用户）
		l.Infof("[handleMobileExists] 场景2.3: 已登录临时用户+手机号存在, 需要合并账号, sourceUserId: %s, targetUserId: %s, authType: %s", currentUserID, userID, currentAuthType)
		return l.mergeTempUserToTarget(ctx, session, currentUserID, userID, currentAuthType, currentAuthKey)
	}
}

// mergeTempUserToTarget 合并临时用户到目标用户
func (l *RegisterByInviteCodeLogic) mergeTempUserToTarget(ctx context.Context, session sqlx.Session, sourceUserID string, targetUserID string, currentAuthType string, currentAuthKey string) (string, error) {
	l.Infof("[mergeTempUserToTarget] 开始合并, sourceUserId: %s, targetUserId: %s, authType: %s", sourceUserID, targetUserID, currentAuthType)

	// 检查目标用户是否已有该认证（除了UUID）
	if currentAuthType != model.UserAuthTypeUUID {
		targetAuth, err := l.svcCtx.UserAuthModel.FindOneByUserIdAuthType(ctx, targetUserID, currentAuthType)
		if err != nil && !errors.Is(err, model.ErrNotFound) {
			return "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查找认证信息失败: %v", err)
		}
		if targetAuth != nil && targetAuth.AuthKey != currentAuthKey {
			// 目标用户已有该类型的其他认证，证明手机号绑定过其他微信等
			l.Infof("[mergeTempUserToTarget] 目标用户已有其他认证, targetUserId: %s, authType: %s, targetAuthKey: %s, currentAuthKey: %s", targetUserID, currentAuthType, targetAuth.AuthKey, currentAuthKey)
			if currentAuthType == model.UserAuthTypeWxh5OpenID {
				return "", errors.Wrapf(xerr.NewErrMsg("该手机号已绑定其他微信号"), "")
			}
			if currentAuthType == model.UserAuthTypeWxMiniOpenID {
				return "", errors.Wrapf(xerr.NewErrMsg("该手机号已绑定其他微信号"), "")
			}
			return "", errors.Wrapf(xerr.NewErrMsg("该手机号已绑定其他终端"), "")
		}
		l.Infof("[mergeTempUserToTarget] 微信唯一性检查通过, targetUserId: %s, authType: %s", targetUserID, currentAuthType)
	}

	// 查找当前认证
	existingAuth, err := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(ctx, currentAuthType, currentAuthKey)
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		return "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查找认证信息失败: %v", err)
	}
	if existingAuth != nil {
		l.Infof("[mergeTempUserToTarget] 找到现有认证, authId: %s, userId: %s", existingAuth.Id, existingAuth.UserId)
	} else {
		l.Infof("[mergeTempUserToTarget] 未找到现有认证, 将创建新认证")
	}

	// 执行账号合并
	if err := l.mergeUserAccounts(ctx, session, sourceUserID, targetUserID, currentAuthType, currentAuthKey, existingAuth); err != nil {
		return "", err
	}

	l.Infof("[mergeTempUserToTarget] 账号合并完成, targetUserId: %s", targetUserID)
	return targetUserID, nil
}

// mergeUserAccounts 合并账号：迁移认证、业务数据，删除临时用户
func (l *RegisterByInviteCodeLogic) mergeUserAccounts(ctx context.Context, session sqlx.Session, sourceUserID string, targetUserID string, currentAuthType string, currentAuthKey string, existingAuth *model.UserAuth) error {
	l.Infof("[mergeUserAccounts] 开始合并账号, sourceUserId: %s, targetUserId: %s, authType: %s", sourceUserID, targetUserID, currentAuthType)

	// 1) 认证绑定处理
	if existingAuth != nil && existingAuth.UserId != targetUserID {
		l.Infof("[mergeUserAccounts] 认证存在但不属于目标用户, 开始迁移认证, authId: %s, currentUserId: %s, targetUserId: %s", existingAuth.Id, existingAuth.UserId, targetUserID)
		// 认证存在但不属于目标用户，迁移到目标用户
		if currentAuthType == model.UserAuthTypeUUID {
			// UUID替换策略：如果目标用户已有UUID认证，替换UUID；否则迁移认证
			l.Infof("[mergeUserAccounts] UUID认证类型, 执行替换策略")
			targetUUIDAuth, _ := l.svcCtx.UserAuthModel.FindOneByUserIdAuthType(ctx, targetUserID, model.UserAuthTypeUUID)
			if targetUUIDAuth != nil {
				// 目标用户已有UUID认证，删除源认证并更新目标UUID
				l.Infof("[mergeUserAccounts] 目标用户已有UUID认证, 删除源认证并更新目标UUID, targetAuthId: %s", targetUUIDAuth.Id)
				if err := l.svcCtx.UserAuthModel.Delete(ctx, session, existingAuth.Id); err != nil {
					return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "删除旧UUID认证失败: %v", err)
				}
				if targetUUIDAuth.AuthKey != currentAuthKey {
					targetUUIDAuth.AuthKey = currentAuthKey
					if _, err := l.svcCtx.UserAuthModel.Update(ctx, session, targetUUIDAuth); err != nil {
						return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新目标UUID认证失败: %v", err)
					}
					l.Infof("[mergeUserAccounts] UUID认证更新成功, authId: %s", targetUUIDAuth.Id)
				}
			} else {
				// 目标用户没有UUID认证，迁移源认证
				l.Infof("[mergeUserAccounts] 目标用户没有UUID认证, 迁移源认证, authId: %s", existingAuth.Id)
				existingAuth.UserId = targetUserID
				if _, err := l.svcCtx.UserAuthModel.Update(ctx, session, existingAuth); err != nil {
					return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "迁移UUID认证失败: %v", err)
				}
				l.Infof("[mergeUserAccounts] UUID认证迁移成功")
			}
		} else {
			// 其他认证类型，直接迁移
			l.Infof("[mergeUserAccounts] 其他认证类型, 直接迁移, authId: %s, authType: %s", existingAuth.Id, currentAuthType)
			existingAuth.UserId = targetUserID
			if _, err := l.svcCtx.UserAuthModel.Update(ctx, session, existingAuth); err != nil {
				return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "迁移认证失败: %v", err)
			}
			l.Infof("[mergeUserAccounts] 认证迁移成功, authId: %s", existingAuth.Id)
		}
	} else if existingAuth == nil {
		// 认证不存在，创建新认证
		l.Infof("[mergeUserAccounts] 认证不存在, 创建新认证, authType: %s", currentAuthType)
		if currentAuthType == model.UserAuthTypeUUID {
			// UUID特殊处理：如果目标用户已有UUID认证，更新UUID；否则创建新认证
			targetUUIDAuth, _ := l.svcCtx.UserAuthModel.FindOneByUserIdAuthType(ctx, targetUserID, model.UserAuthTypeUUID)
			if targetUUIDAuth != nil {
				l.Infof("[mergeUserAccounts] 目标用户已有UUID认证, 更新UUID, authId: %s", targetUUIDAuth.Id)
				if targetUUIDAuth.AuthKey != currentAuthKey {
					targetUUIDAuth.AuthKey = currentAuthKey
					if _, err := l.svcCtx.UserAuthModel.Update(ctx, session, targetUUIDAuth); err != nil {
						return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新目标UUID认证失败: %v", err)
					}
					l.Infof("[mergeUserAccounts] UUID认证更新成功")
				}
			} else {
				newAuth := &model.UserAuth{
					Id:       uuid.NewString(),
					UserId:   targetUserID,
					AuthType: currentAuthType,
					AuthKey:  currentAuthKey,
				}
				if _, err := l.svcCtx.UserAuthModel.Insert(ctx, session, newAuth); err != nil {
					return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建UUID认证失败: %v", err)
				}
				l.Infof("[mergeUserAccounts] UUID认证创建成功, authId: %s", newAuth.Id)
			}
		} else {
			// 其他认证类型，创建新认证
			newAuth := &model.UserAuth{
				Id:       uuid.NewString(),
				UserId:   targetUserID,
				AuthType: currentAuthType,
				AuthKey:  currentAuthKey,
			}
			if _, err := l.svcCtx.UserAuthModel.Insert(ctx, session, newAuth); err != nil {
				return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建认证失败: %v", err)
			}
			l.Infof("[mergeUserAccounts] 认证创建成功, authId: %s, authType: %s", newAuth.Id, currentAuthType)
		}
	}

	// 2) 业务数据迁移：迁移订单和报告到目标用户
	l.Infof("[mergeUserAccounts] 开始迁移业务数据, sourceUserId: %s, targetUserId: %s", sourceUserID, targetUserID)
	if err := l.svcCtx.OrderModel.UpdateUserIDWithSession(ctx, session, sourceUserID, targetUserID); err != nil {
		return errors.Wrapf(err, "迁移订单失败")
	}
	l.Infof("[mergeUserAccounts] 订单迁移完成")
	if err := l.svcCtx.QueryModel.UpdateUserIDWithSession(ctx, session, sourceUserID, targetUserID); err != nil {
		return errors.Wrapf(err, "迁移报告失败")
	}
	l.Infof("[mergeUserAccounts] 报告迁移完成")

	// 3) 删除临时用户
	l.Infof("[mergeUserAccounts] 开始删除临时用户, sourceUserId: %s", sourceUserID)
	sourceUser, err := l.svcCtx.UserModel.FindOne(ctx, sourceUserID)
	if err != nil {
		return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查找源用户失败: %v", err)
	}
	if err := l.svcCtx.UserModel.Delete(ctx, session, sourceUser.Id); err != nil {
		return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "删除源用户失败: %v", err)
	}
	l.Infof("[mergeUserAccounts] 临时用户删除成功, sourceUserId: %s", sourceUserID)
	l.Infof("[mergeUserAccounts] 账号合并完成, targetUserId: %s", targetUserID)

	return nil
}
