package repository

import (
	"testing"

	"hyapp-admin-server/internal/model"

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

func TestReplaceAndListUserMoneyScopes(t *testing.T) {
	store, mock, closeStore := newRepositorySQLMock(t)
	defer closeStore()

	mock.ExpectBegin()
	mock.ExpectQuery("SELECT \\* FROM `admin_users` WHERE `admin_users`.`id` = \\? ORDER BY `admin_users`.`id` LIMIT \\?").
		WillReturnRows(sqlmock.NewRows([]string{"id", "username", "name", "status"}).AddRow(7, "ops", "Ops", "active"))
	mock.ExpectExec("DELETE FROM `admin_user_money_scopes` WHERE user_id = \\?").
		WillReturnResult(sqlmock.NewResult(0, 2))
	mock.ExpectExec("INSERT INTO `admin_user_money_scopes`").
		WillReturnResult(sqlmock.NewResult(1, 2))
	mock.ExpectCommit()

	if err := store.ReplaceUserMoneyScopes(7, []model.UserMoneyScope{
		{AppCode: " LALU ", RegionID: 2},
		{AppCode: "lalu", RegionID: 2},
		{AppCode: "yumi", RegionID: 0},
	}); err != nil {
		t.Fatalf("replace money scopes failed: %v", err)
	}

	mock.ExpectQuery("SELECT \\* FROM `admin_user_money_scopes` WHERE user_id = \\? ORDER BY app_code ASC, region_id ASC").
		WillReturnRows(sqlmock.NewRows([]string{"id", "user_id", "app_code", "region_id", "created_at_ms", "updated_at_ms"}).
			AddRow(1, 7, "lalu", 2, int64(1700000000000), int64(1700000000000)).
			AddRow(2, 7, "yumi", 0, int64(1700000000000), int64(1700000000000)))

	scopes, err := store.ListUserMoneyScopes(7)
	if err != nil {
		t.Fatalf("list money scopes failed: %v", err)
	}
	if len(scopes) != 2 || scopes[0].AppCode != "lalu" || scopes[0].RegionID != 2 || scopes[1].AppCode != "yumi" || scopes[1].RegionID != 0 {
		t.Fatalf("money scopes mismatch: %+v", scopes)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("sql expectations mismatch: %v", err)
	}
}

func TestReplaceUserMoneyScopesRejectsInvalidScope(t *testing.T) {
	store, mock, closeStore := newRepositorySQLMock(t)
	defer closeStore()

	if err := store.ReplaceUserMoneyScopes(7, []model.UserMoneyScope{{RegionID: 2}}); err == nil {
		t.Fatal("expected invalid scope error")
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("sql expectations mismatch: %v", err)
	}
}

func newRepositorySQLMock(t *testing.T) (*Store, sqlmock.Sqlmock, func()) {
	t.Helper()
	sqlDB, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("create sql mock failed: %v", err)
	}
	gormDB, err := gorm.Open(mysql.New(mysql.Config{Conn: sqlDB, SkipInitializeWithVersion: true}), &gorm.Config{})
	if err != nil {
		_ = sqlDB.Close()
		t.Fatalf("create gorm db failed: %v", err)
	}
	return New(gormDB), mock, func() {
		_ = sqlDB.Close()
	}
}
