package orderLogic

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	commonLogic "github.com/perfect-panel/server/internal/logic/common"
	"github.com/perfect-panel/server/internal/model/order"
	"github.com/perfect-panel/server/internal/model/subscribe"
	internaltypes "github.com/perfect-panel/server/internal/types"
	"github.com/redis/go-redis/v9"
	"gorm.io/gorm"
)

func validateNewUserOnlyEligibilityAtActivation(
	ctx context.Context,
	db *gorm.DB,
	rdb *redis.Client,
	orderInfo *order.Order,
	sub *subscribe.Subscribe,
) error {
	if orderInfo == nil || sub == nil || orderInfo.Type != OrderTypeSubscribe || sub.Discount == "" {
		return nil
	}

	var discounts []internaltypes.SubscribeDiscount
	if err := json.Unmarshal([]byte(sub.Discount), &discounts); err != nil {
		return nil
	}
	if !isNewUserOnlyForQuantity(discounts, orderInfo.Quantity) {
		return nil
	}

	// Acquire a per-user distributed lock so concurrent new-user-only activations
	// for the same account are serialised. Without this, two workers can both read
	// historyCount=0 and both pass the check before either has written the order.
	lockKey := fmt.Sprintf("new_user_only_activate:%d", orderInfo.UserId)
	const lockTTL = 30 * time.Second
	acquired, lockErr := rdb.SetNX(ctx, lockKey, orderInfo.OrderNo, lockTTL).Result()
	if lockErr != nil {
		return fmt.Errorf("new user only: acquire lock error: %w", lockErr)
	}
	if !acquired {
		return fmt.Errorf("new user only: another activation is in progress for user %d", orderInfo.UserId)
	}
	defer rdb.Del(ctx, lockKey)

	eligibility, err := commonLogic.ResolveNewUserEligibility(ctx, db, orderInfo.UserId)
	if err != nil {
		return err
	}
	if !eligibility.IsNewUserAt(time.Now()) {
		return fmt.Errorf("new user only: user %d is not a new user", orderInfo.UserId)
	}

	historyCount, err := commonLogic.CountScopedSubscribePurchaseOrders(
		ctx,
		db,
		eligibility.ScopeUserIDs,
		0,
		[]int64{OrderStatusFinished},
		orderInfo.OrderNo,
	)
	if err != nil {
		return fmt.Errorf("new user only: check history error: %w", err)
	}
	if historyCount >= 1 {
		return fmt.Errorf("new user only: user %d already activated an order", orderInfo.UserId)
	}

	return nil
}
