package user

import (
	"context"
	"testing"

	"bindbox-game/internal/repository/mysql/dao"

	"github.com/DATA-DOG/go-sqlmock"
	"github.com/stretchr/testify/assert"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

func setupMockDB(t *testing.T) (*gorm.DB, sqlmock.Sqlmock) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
	}
	gormDB, err := gorm.Open(mysql.New(mysql.Config{
		Conn:                      db,
		SkipInitializeWithVersion: true,
	}), &gorm.Config{})
	if err != nil {
		t.Fatalf("an error '%s' was not expected when opening gorm database", err)
	}
	return gormDB, mock
}

func newTestService(db *gorm.DB) *service {
	q := dao.Use(db)
	return &service{
		readDB:  q,
		writeDB: q,
	}
}

func TestAddItemCard_NotFound(t *testing.T) {
	db, mock := setupMockDB(t)
	svc := newTestService(db)

	mock.ExpectQuery("SELECT .* FROM `system_item_cards`").
		WithArgs(100, sqlmock.AnyArg()).
		WillReturnRows(sqlmock.NewRows(nil)) // Not found

	err := svc.AddItemCard(context.Background(), 1, 100, 1)
	assert.Error(t, err)
	assert.Equal(t, "record not found", err.Error())
}

func TestAddItemCard_Disabled(t *testing.T) {
	db, mock := setupMockDB(t)
	svc := newTestService(db)

	rows := sqlmock.NewRows([]string{"id", "status"}).AddRow(100, 0)
	mock.ExpectQuery("SELECT .* FROM `system_item_cards`").
		WithArgs(100, sqlmock.AnyArg()).
		WillReturnRows(rows)

	err := svc.AddItemCard(context.Background(), 1, 100, 1)
	assert.Error(t, err)
	assert.Equal(t, "item card not found or disabled", err.Error())
}

func TestAddCoupon_NotFound(t *testing.T) {
	db, mock := setupMockDB(t)
	svc := newTestService(db)

	mock.ExpectQuery("SELECT .* FROM `system_coupons`").
		WithArgs(200, sqlmock.AnyArg()).
		WillReturnRows(sqlmock.NewRows(nil))

	err := svc.AddCoupon(context.Background(), 1, 200)
	assert.Error(t, err)
	assert.Equal(t, "record not found", err.Error())
}

func TestAddCoupon_Disabled(t *testing.T) {
	db, mock := setupMockDB(t)
	svc := newTestService(db)

	rows := sqlmock.NewRows([]string{"id", "status"}).AddRow(200, 0)
	mock.ExpectQuery("SELECT .* FROM `system_coupons`").
		WithArgs(200, sqlmock.AnyArg()).
		WillReturnRows(rows)

	err := svc.AddCoupon(context.Background(), 1, 200)
	assert.Error(t, err)
	assert.Equal(t, "coupon not found or disabled", err.Error())
}
