package agent

import (
	"context"
	"database/sql"
	stderrors "errors"
	"fmt"
	"jnc-server/app/main/model"
	"jnc-server/common/ctxdata"
	"jnc-server/common/xerr"
	"jnc-server/pkg/lzkit/crypto"
	"os"
	"time"

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

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

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

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

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

func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *types.AgentApplyResp, err error) {
	claims, err := ctxdata.GetClaimsFromCtx(l.ctx)
	if err != nil && !stderrors.Is(err, ctxdata.ErrNoInCtx) {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请失败, %v", err)
	}

	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)
	}

	// 系统简化：无需邀请码,直接申请成为代理
	if req.Referrer == "" {
		return nil, errors.Wrapf(xerr.NewErrMsg("请填写邀请信息"), "")
	}

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

	var userID string
	transErr := l.svcCtx.AgentModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
		// 1. 处理用户注册/绑定
		user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
		if findUserErr != nil && !stderrors.Is(findUserErr, model.ErrNotFound) {
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询用户失败, %v", findUserErr)
		}

		if user == nil {
			// 用户不存在，注册新用户
			if claims != nil && claims.UserType == model.UserTypeNormal {
				return errors.Wrapf(xerr.NewErrMsg("当前用户已注册，请输入注册的手机号"), "")
			}
			userID, err = l.svcCtx.UserService.RegisterUser(l.ctx, encryptedMobile)
			if err != nil {
				return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "注册用户失败: %v", err)
			}
		} else {
			// 用户已存在
			if claims != nil && claims.UserType == model.UserTypeTemp {
				// 临时用户，检查手机号是否已绑定其他微信号
				userAuth, findUserAuthErr := l.svcCtx.UserAuthModel.FindOneByUserIdAuthType(l.ctx, user.Id, claims.AuthType)
				if findUserAuthErr != nil && !stderrors.Is(findUserAuthErr, model.ErrNotFound) {
					return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询用户认证失败, %v", findUserAuthErr)
				}
				if userAuth != nil && userAuth.AuthKey != claims.AuthKey {
					return errors.Wrapf(xerr.NewErrMsg("该手机号已绑定其他微信号"), "")
				}
				// 临时用户，转为正式用户
				err = l.svcCtx.UserService.TempUserBindUser(l.ctx, session, user.Id)
				if err != nil {
					return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "绑定用户失败: %v", err)
				}
			}
			userID = user.Id
		}

		// 3. 检查是否已是代理
		existingAgent, err := l.svcCtx.AgentModel.FindOneByUserId(transCtx, userID)
		if err != nil && !stderrors.Is(err, model.ErrNotFound) {
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败, %v", err)
		}
		if existingAgent != nil {
			return errors.Wrapf(xerr.NewErrMsg("您已经是代理"), "")
		}

		// 系统简化：移除邀请码验证、等级设置、团队关系建立等复杂逻辑
		// 4. 分配代理编码
		agentCode, err := l.allocateAgentCode(transCtx, session)
		if err != nil {
			return errors.Wrapf(err, "分配代理编码失败")
		}

		// 5. 创建代理记录（简化版：无等级、无团队首领）
		newAgent := &model.Agent{
			Id:        uuid.NewString(),
			UserId:    userID,
			AgentCode: agentCode,
			Mobile:    encryptedMobile,
		}
		if req.Region != "" {
			newAgent.Region = sql.NullString{String: req.Region, Valid: true}
		}

		_, err = l.svcCtx.AgentModel.Insert(transCtx, session, newAgent)
		if err != nil {
			return errors.Wrapf(err, "创建代理记录失败")
		}

		// 6. 初始化钱包（简化版：移除冻结余额、提现金额字段）
		wallet := &model.AgentWallet{
			Id:      uuid.NewString(),
			AgentId: newAgent.Id,
		}
		if _, err := l.svcCtx.AgentWalletModel.Insert(transCtx, session, wallet); err != nil {
			return errors.Wrapf(err, "初始化钱包失败")
		}

		return nil
	})

	if transErr != nil {
		return nil, transErr
	}

	// 7. 生成并返回token
	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)
	}

	now := time.Now().Unix()
	agent, _ := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
	var code int64
	if agent != nil {
		code = agent.AgentCode
	}
	return &types.AgentApplyResp{
		AccessToken:  token,
		AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
		RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
		AgentCode:    code,
	}, nil
}

// allocateAgentCode 分配代理编码
func (l *ApplyForAgentLogic) 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
}
