package agent

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

	"github.com/pkg/errors"

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

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

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

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

func (l *GetInviteLinkLogic) GetInviteLink(req *types.GetInviteLinkReq) (resp *types.GetInviteLinkResp, err error) {
	// 1. 获取当前代理信息
	userID, err := ctxdata.GetUidFromCtx(l.ctx)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户信息失败, %v", err)
	}

	agent, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
	if err != nil {
		if errors.Is(err, model.ErrNotFound) {
			return nil, errors.Wrapf(xerr.NewErrMsg("您不是代理"), "")
		}
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败, %v", err)
	}

	// 2. 验证邀请码参数
	if req.InviteCode == "" {
		return nil, errors.Wrapf(xerr.NewErrMsg("邀请码不能为空"), "")
	}

	ref := strings.TrimSpace(req.InviteCode)
	var inviteCodeRecord *model.AgentInviteCode
	inviteCodeRecord, err = l.svcCtx.AgentInviteCodeModel.FindOneByCode(l.ctx, ref)
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询邀请码失败, %v", err)
	}

	if inviteCodeRecord != nil {
		if !inviteCodeRecord.AgentId.Valid || inviteCodeRecord.AgentId.String != agent.Id {
			return nil, errors.Wrapf(xerr.NewErrMsg("无权使用此邀请码"), "")
		}
		if inviteCodeRecord.Status != 0 {
			if inviteCodeRecord.Status == 1 {
				return nil, errors.Wrapf(xerr.NewErrMsg("邀请码已使用"), "")
			}
			return nil, errors.Wrapf(xerr.NewErrMsg("邀请码已失效"), "")
		}
		if inviteCodeRecord.ExpireTime.Valid && inviteCodeRecord.ExpireTime.Time.Before(time.Now()) {
			return nil, errors.Wrapf(xerr.NewErrMsg("邀请码已过期"), "")
		}
	} else {
		if codeVal, parseErr := strconv.ParseInt(ref, 10, 64); parseErr == nil && codeVal > 0 {
			if agent.AgentCode != codeVal {
				return nil, errors.Wrapf(xerr.NewErrMsg("无权使用此邀请码"), "")
			}
		} else {
			encMobile, _ := crypto.EncryptMobile(ref, l.svcCtx.Config.Encrypt.SecretKey)
			if encMobile != agent.Mobile {
				return nil, errors.Wrapf(xerr.NewErrMsg("邀请信息无效"), "")
			}
		}
	}

	// 7. 使用默认target_path（如果未提供）
	targetPath := req.TargetPath
	if targetPath == "" {
		targetPath = fmt.Sprintf("/register?invite_code=%s", ref)
	}

	shortLink, err := l.createInviteShortLink(func() string {
		if inviteCodeRecord != nil {
			return inviteCodeRecord.Id
		}
		return ""
	}(), ref, targetPath)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成短链失败, %v", err)
	}

	return &types.GetInviteLinkResp{
		InviteLink: shortLink,
	}, nil
}

// createInviteShortLink 创建邀请好友短链
func (l *GetInviteLinkLogic) createInviteShortLink(inviteCodeId string, inviteCode, targetPath string) (string, error) {
	promotionConfig := l.svcCtx.Config.Promotion

	// 如果没有配置推广域名，返回空字符串（保持向后兼容）
	if promotionConfig.PromotionDomain == "" {
		l.Errorf("推广域名未配置，返回空链接")
		return "", nil
	}

	// 先查询是否已存在短链
	existingShortLink, err := l.svcCtx.AgentShortLinkModel.FindOneByInviteCodeIdTypeDelState(l.ctx, sql.NullString{String: inviteCodeId, Valid: inviteCodeId != ""}, 2, globalkey.DelStateNo)
	if err == nil && existingShortLink != nil {
		// 已存在短链，直接返回
		return fmt.Sprintf("%s/s/%s", promotionConfig.PromotionDomain, existingShortLink.ShortCode), nil
	}

	if err != nil && !errors.Is(err, model.ErrNotFound) {
		return "", errors.Wrapf(err, "查询短链失败")
	}

	// 如果没有邀请码ID（例如使用手机号或代理码），按邀请码字符串尝试查找以避免重复创建
	if inviteCodeId == "" && inviteCode != "" {
		existingByCode, err2 := l.svcCtx.AgentShortLinkModel.FindOneByInviteCodeTypeDelState(l.ctx, sql.NullString{String: inviteCode, Valid: true}, 2, globalkey.DelStateNo)
		if err2 == nil && existingByCode != nil {
			return fmt.Sprintf("%s/s/%s", promotionConfig.PromotionDomain, existingByCode.ShortCode), nil
		}
		if err2 != nil && !errors.Is(err2, model.ErrNotFound) {
			return "", errors.Wrapf(err2, "查询短链失败")
		}
	}

	// 生成短链标识（6位随机字符串，大小写字母+数字）
	var shortCode string
	maxRetries := 10 // 最大重试次数
	for retry := 0; retry < maxRetries; retry++ {
		shortCode = tool.Krand(6, tool.KC_RAND_KIND_ALL)
		// 检查短链标识是否已存在
		_, err := l.svcCtx.AgentShortLinkModel.FindOneByShortCodeDelState(l.ctx, shortCode, globalkey.DelStateNo)
		if err != nil {
			if errors.Is(err, model.ErrNotFound) {
				// 短链标识不存在，可以使用
				break
			}
			return "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "检查短链标识失败, %v", err)
		}
		// 短链标识已存在，继续生成
		if retry == maxRetries-1 {
			return "", errors.Wrapf(xerr.NewErrMsg("生成短链失败，请重试"), "")
		}
	}

	// 创建短链记录（类型：2=邀请好友）
	shortLink := &model.AgentShortLink{
		Id:              uuid.NewString(),
		Type:            2, // 邀请好友
		InviteCodeId:    sql.NullString{String: inviteCodeId, Valid: inviteCodeId != ""},
		InviteCode:      sql.NullString{String: inviteCode, Valid: inviteCode != ""},
		ShortCode:       shortCode,
		TargetPath:      targetPath,
		PromotionDomain: promotionConfig.PromotionDomain,
	}
	_, err = l.svcCtx.AgentShortLinkModel.Insert(l.ctx, nil, shortLink)
	if err != nil {
		return "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "保存短链失败, %v", err)
	}

	return fmt.Sprintf("%s/s/%s", promotionConfig.PromotionDomain, shortCode), nil
}
