package giftdiamond

import (
	"context"
	"errors"
	"regexp"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
)

func TestPersistedPercentStringRejectsEmptyOrInvalidValues(t *testing.T) {
	for _, raw := range []string{"", "bad", "-1", "101"} {
		if _, err := persistedPercentString(raw); err == nil {
			t.Fatalf("persisted percent %q must not be replaced by a code default", raw)
		}
	}
	if got, err := persistedPercentString("12.345"); err != nil || got != "12.35" {
		t.Fatalf("valid persisted percent mismatch: got=%q err=%v", got, err)
	}
}

func TestResolveRatioReturnsUnconfiguredInsteadOfSyntheticDefaults(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("create sqlmock: %v", err)
	}
	defer db.Close()
	query := regexp.QuoteMeta(`
		SELECT region_id, gift_type_code, CAST(ratio_percent AS CHAR), CAST(coin_return_ratio_percent AS CHAR), status, updated_at_ms
		FROM gift_diamond_ratio_configs
		WHERE app_code = ? AND region_id = ? AND gift_type_code = ?
		LIMIT 1`)
	mock.ExpectQuery(query).WithArgs("fami", int64(25), "normal").WillReturnError(sqlmock.ErrCancelled)
	service := NewService(db)
	if _, _, err := service.resolveRatio(context.Background(), "fami", 25, "normal"); !errors.Is(err, sqlmock.ErrCancelled) {
		t.Fatalf("query errors must be returned: %v", err)
	}

	// 两级查询均无记录时必须返回 configured=false，不能显示 100/10/1 幽灵政策。
	mock.ExpectQuery(query).WithArgs("fami", int64(25), "normal").WillReturnRows(sqlmock.NewRows([]string{"region_id", "gift_type_code", "ratio", "return_ratio", "status", "updated_at_ms"}))
	mock.ExpectQuery(query).WithArgs("fami", int64(0), "normal").WillReturnRows(sqlmock.NewRows([]string{"region_id", "gift_type_code", "ratio", "return_ratio", "status", "updated_at_ms"}))
	item, configured, err := service.resolveRatio(context.Background(), "fami", 25, "normal")
	if err != nil || configured || item != (ratioDTO{}) {
		t.Fatalf("unconfigured ratio mismatch: item=%+v configured=%t err=%v", item, configured, err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("unmet SQL expectations: %v", err)
	}
}

func TestEnsureSchemaDoesNotInsertGiftMultiplierDefaults(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("create sqlmock: %v", err)
	}
	defer db.Close()
	mock.ExpectExec("CREATE TABLE IF NOT EXISTS gift_diamond_ratio_configs").WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectExec("ALTER TABLE gift_diamond_ratio_configs").WillReturnError(errors.New("Duplicate column name 'coin_return_ratio_percent'"))
	if err := NewService(db).ensureSchema(context.Background()); err != nil {
		t.Fatalf("ensure schema: %v", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("startup must not issue an implicit INSERT: %v", err)
	}
}
