package admin_promotion

import (
	"context"
	"crypto/rand"
	"fmt"
	"math/big"
	"time"

	"xingfucha-server/app/main/api/internal/svc"
	"xingfucha-server/app/main/api/internal/types"
	"xingfucha-server/app/main/model"
	"xingfucha-server/common/ctxdata"
	"xingfucha-server/common/xerr"

	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

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

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

// 生成6位随机字符串（大小写字母和数字）
func generateRandomString() (string, error) {
	const (
		chars  = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
		length = 6
	)

	result := make([]byte, length)
	for i := 0; i < length; i++ {
		num, err := rand.Int(rand.Reader, big.NewInt(int64(len(chars))))
		if err != nil {
			return "", err
		}
		result[i] = chars[num.Int64()]
	}
	return string(result), nil
}

func (l *CreatePromotionLinkLogic) CreatePromotionLink(req *types.CreatePromotionLinkReq) (resp *types.CreatePromotionLinkResp, err error) {
	// 获取当前用户ID
	adminUserId, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
	if getUidErr != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "创建推广链接, 获取用户信息失败, %+v", getUidErr)
	}

	// 生成唯一URL
	var url string
	maxRetries := 5 // 最大重试次数
	for i := 0; i < maxRetries; i++ {
		// 生成6位随机字符串
		randomStr, err := generateRandomString()
		if err != nil {
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "创建推广链接, 生成随机字符串失败, %+v", err)
		}

		// 检查URL是否已存在
		existLink, err := l.svcCtx.AdminPromotionLinkModel.FindOneByUrl(l.ctx, randomStr)
		if err != nil && !errors.Is(err, model.ErrNotFound) {
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建推广链接, 检查URL是否存在失败, %+v", err)
		}

		if existLink != nil {
			continue // URL已存在，继续尝试
		}

		// URL可用
		url = randomStr
		break
	}

	if url == "" {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "创建推广链接失败, 多次尝试生成唯一URL均失败")
	}
	url = fmt.Sprintf("%s/%s", l.svcCtx.Config.AdminPromotion.URLDomain, url)
	// 创建推广链接
	link := &model.AdminPromotionLink{
		Name:        req.Name,
		Url:         url,
		AdminUserId: adminUserId,
	}

	var linkId int64
	err = l.svcCtx.AdminPromotionLinkModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
		result, err := l.svcCtx.AdminPromotionLinkModel.Insert(l.ctx, session, link)
		if err != nil {
			return fmt.Errorf("创建推广链接失败, %+v", err)
		}

		linkId, err = result.LastInsertId()
		if err != nil {
			return fmt.Errorf("获取推广链接ID失败, %+v", err)
		}

		// 创建总统计记录
		totalStats := &model.AdminPromotionLinkStatsTotal{
			LinkId: linkId,
		}
		_, err = l.svcCtx.AdminPromotionLinkStatsTotalModel.Insert(l.ctx, session, totalStats)
		if err != nil {
			return fmt.Errorf("创建推广链接总统计记录失败, %+v", err)
		}

		// 创建统计历史记录
		historyStats := &model.AdminPromotionLinkStatsHistory{
			LinkId:    linkId,
			StatsDate: time.Now().Truncate(24 * time.Hour),
		}
		_, err = l.svcCtx.AdminPromotionLinkStatsHistoryModel.Insert(l.ctx, session, historyStats)
		if err != nil {
			return fmt.Errorf("创建推广链接统计历史记录失败, %+v", err)
		}
		return nil
	})
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建推广链接失败, %+v", err)
	}

	return &types.CreatePromotionLinkResp{
		Id:  linkId,
		Url: url,
	}, nil
}
