package packs

import (
	"context"
	"regexp"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
	"github.com/nexuscrm/shared/pkg/constants"
)

func TestListSetupObjectBackfillTargetsIncludesReadOnlyFields(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock: %v", err)
	}
	defer db.Close()

	rows := sqlmock.NewRows([]string{
		constants.FieldSysObject_APIName,
		constants.FieldSysObject_RequiredWritePermission,
		constants.FieldSysField_APIName,
		constants.FieldSysField_Createable,
		constants.FieldSysField_Updateable,
	}).
		AddRow("User", "ViewSetup", "Email", true, true).
		AddRow("User", "ViewSetup", "Name", false, false).
		AddRow("User", "ViewSetup", "LastLoginDate", false, false)

	mock.ExpectQuery(regexp.QuoteMeta("SELECT")).
		WillReturnRows(rows)

	targets, err := listSetupObjectBackfillTargets(context.Background(), db)
	if err != nil {
		t.Fatalf("listSetupObjectBackfillTargets: %v", err)
	}
	if len(targets) != 1 {
		t.Fatalf("targets len = %d; want 1", len(targets))
	}
	if got := targets[0].APIName; got != "User" {
		t.Fatalf("APIName = %q; want User", got)
	}
	if got := targets[0].RequiredWritePermission; got != "ViewSetup" {
		t.Fatalf("RequiredWritePermission = %q; want ViewSetup", got)
	}
	if got := targets[0].FieldAPINames; len(got) != 3 || got[0] != "Email" || got[1] != "Name" || got[2] != "LastLoginDate" {
		t.Fatalf("FieldAPINames = %#v; want [Email Name LastLoginDate]", got)
	}

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("sql expectations: %v", err)
	}
}

func TestBackfillSetupObjectPermissionsFromSystemPermsBuildsRunnableSQL(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock: %v", err)
	}
	defer db.Close()

	rows := sqlmock.NewRows([]string{
		constants.FieldSysObject_APIName,
		constants.FieldSysObject_RequiredWritePermission,
		constants.FieldSysField_APIName,
		constants.FieldSysField_Createable,
		constants.FieldSysField_Updateable,
	}).
		AddRow("User", "ViewSetup", "Email", true, true).
		AddRow("User", "ViewSetup", "Name", false, false)

	mock.ExpectQuery(regexp.QuoteMeta("SELECT")).WillReturnRows(rows)
	mock.ExpectExec(regexp.QuoteMeta("INSERT IGNORE INTO `ObjectPermissions`")).
		WithArgs("User", "ViewSetup").
		WillReturnResult(sqlmock.NewResult(0, 1))
	mock.ExpectExec("INSERT IGNORE INTO `FieldPermissions`[\\s\\S]*f\\.ApiName IN \\(\\?,\\?\\)").
		WithArgs("User", "ViewSetup", "Email", "Name").
		WillReturnResult(sqlmock.NewResult(0, 2))

	if err := BackfillSetupObjectPermissionsFromSystemPerms(context.Background(), db); err != nil {
		t.Fatalf("BackfillSetupObjectPermissionsFromSystemPerms: %v", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("sql expectations: %v", err)
	}
}
