package appconfig

import (
	"context"
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
)

const (
	giftConfigGroup            = "room-gift"
	giftQuantityPresetsKey     = "quantity-presets"
	giftQuantityPresetMaxCount = 8
	giftQuantityPresetMaxValue = 9_999
)

const getGiftQuantityPresetsSQL = `
	SELECT COALESCE(value, '')
	FROM admin_app_configs
	WHERE app_code = ? AND ` + "`group`" + ` = ? AND ` + "`key`" + ` = ? AND is_deleted = FALSE
	LIMIT 1`

// DefaultGiftQuantityPresets preserves the existing product behavior for Apps that have not saved
// their own room-gift configuration. Callers receive a copy so request-local fallback cannot mutate it.
func DefaultGiftQuantityPresets() []int32 {
	return []int32{1, 9, 99, 999}
}

// GiftQuantityPresets resolves only the selected App's row. The three-column unique index makes this
// a bounded point lookup; a missing row is a normal compatibility fallback, not a cross-App baseline.
func (r *MySQLReader) GiftQuantityPresets(ctx context.Context, appCode string) ([]int32, error) {
	if r == nil || r.db == nil {
		return nil, errors.New("app config reader is not configured")
	}
	appCode = normalizeAppCode(appCode)
	var raw string
	err := r.db.QueryRowContext(ctx, getGiftQuantityPresetsSQL, appCode, giftConfigGroup, giftQuantityPresetsKey).Scan(&raw)
	if errors.Is(err, sql.ErrNoRows) {
		return DefaultGiftQuantityPresets(), nil
	}
	if err != nil {
		return nil, err
	}
	var presets []int32
	if err := json.Unmarshal([]byte(strings.TrimSpace(raw)), &presets); err != nil {
		return nil, fmt.Errorf("parse gift quantity presets for app %s: %w", appCode, err)
	}
	return normalizeGiftQuantityPresets(presets)
}

func normalizeGiftQuantityPresets(values []int32) ([]int32, error) {
	if len(values) == 0 || len(values) > giftQuantityPresetMaxCount {
		return nil, fmt.Errorf("gift quantity presets must contain between 1 and %d values", giftQuantityPresetMaxCount)
	}
	normalized := make([]int32, len(values))
	var previous int32
	for index, value := range values {
		if value < 1 || value > giftQuantityPresetMaxValue {
			return nil, fmt.Errorf("gift quantity preset must be between 1 and %d", giftQuantityPresetMaxValue)
		}
		if index > 0 && value <= previous {
			return nil, errors.New("gift quantity presets must be strictly increasing and unique")
		}
		normalized[index] = value
		previous = value
	}
	return normalized, nil
}

var _ interface {
	GiftQuantityPresets(context.Context, string) ([]int32, error)
} = (*MySQLReader)(nil)
