package services

import (
	"encoding/json"
	"errors"
	"fmt"
	"path/filepath"
	"strings"
	"sync"
	"testing"
	"time"

	"git.mchus.pro/mchus/quoteforge/internal/localdb"
	"git.mchus.pro/mchus/quoteforge/internal/models"
	syncsvc "git.mchus.pro/mchus/quoteforge/internal/services/sync"
)

func TestSaveCreatesNewVersionAndUpdatesCurrentPointer(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "v1",
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 1, UnitPrice: 1000}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}

	if _, err := service.UpdateNoAuth(created.UUID, &CreateConfigRequest{
		Name:        "v1",
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 2, UnitPrice: 1000}},
		ServerCount: 1,
	}); err != nil {
		t.Fatalf("update config: %v", err)
	}

	versions := loadVersions(t, local, created.UUID)
	if len(versions) != 2 {
		t.Fatalf("expected 2 versions, got %d", len(versions))
	}
	if versions[0].VersionNo != 1 || versions[1].VersionNo != 2 {
		t.Fatalf("expected version_no [1,2], got [%d,%d]", versions[0].VersionNo, versions[1].VersionNo)
	}

	cfg, err := local.GetConfigurationByUUID(created.UUID)
	if err != nil {
		t.Fatalf("load local config: %v", err)
	}
	if cfg.CurrentVersionID == nil || *cfg.CurrentVersionID != versions[1].ID {
		t.Fatalf("current_version_id should point to v2")
	}
}

func TestRollbackCreatesNewVersionWithTargetData(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "base",
		Items:       models.ConfigItems{{LotName: "RAM_A", Quantity: 2, UnitPrice: 100}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}

	if _, err := service.UpdateNoAuth(created.UUID, &CreateConfigRequest{
		Name:        "base",
		Items:       models.ConfigItems{{LotName: "RAM_A", Quantity: 3, UnitPrice: 100}},
		ServerCount: 1,
	}); err != nil {
		t.Fatalf("update config: %v", err)
	}
	if _, err := service.RollbackToVersionWithNote(created.UUID, 1, "tester", "test rollback"); err != nil {
		t.Fatalf("rollback to v1: %v", err)
	}

	versions := loadVersions(t, local, created.UUID)
	if len(versions) != 3 {
		t.Fatalf("expected 3 versions, got %d", len(versions))
	}
	if versions[2].VersionNo != 3 {
		t.Fatalf("expected v3 as rollback version, got v%d", versions[2].VersionNo)
	}
	if versions[2].Data != versions[0].Data {
		t.Fatalf("expected rollback snapshot data equal to v1 data")
	}
}

func TestUpdateNoAuthSkipsRevisionWhenSpecAndPriceUnchanged(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "dedupe",
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 1, UnitPrice: 1000}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}

	_, err = service.UpdateNoAuth(created.UUID, &CreateConfigRequest{
		Name:        "dedupe",
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 2, UnitPrice: 1000}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("first update config: %v", err)
	}

	_, err = service.UpdateNoAuth(created.UUID, &CreateConfigRequest{
		Name:        "dedupe",
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 2, UnitPrice: 1000}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("second update config: %v", err)
	}

	versions := loadVersions(t, local, created.UUID)
	if len(versions) != 2 {
		t.Fatalf("expected 2 versions (create + first update), got %d", len(versions))
	}
	if versions[1].VersionNo != 2 {
		t.Fatalf("expected latest version_no=2, got %d", versions[1].VersionNo)
	}

	var pendingCount int64
	if err := local.DB().
		Table("pending_changes").
		Where("entity_type = ? AND entity_uuid = ?", "configuration", created.UUID).
		Count(&pendingCount).Error; err != nil {
		t.Fatalf("count pending changes: %v", err)
	}
	if pendingCount != 2 {
		t.Fatalf("expected 2 pending changes (create + first update), got %d", pendingCount)
	}
}

func TestUpdateNoAuthCreatesRevisionWhenPricingSettingsChanged(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "pricing",
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 1, UnitPrice: 1000}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}

	if _, err := service.UpdateNoAuth(created.UUID, &CreateConfigRequest{
		Name:                "pricing",
		Items:               models.ConfigItems{{LotName: "CPU_A", Quantity: 1, UnitPrice: 1000}},
		ServerCount:         1,
		DisablePriceRefresh: true,
		OnlyInStock:         true,
	}); err != nil {
		t.Fatalf("update pricing settings: %v", err)
	}

	versions := loadVersions(t, local, created.UUID)
	if len(versions) != 2 {
		t.Fatalf("expected 2 versions after pricing settings change, got %d", len(versions))
	}
	if versions[1].VersionNo != 2 {
		t.Fatalf("expected latest version_no=2, got %d", versions[1].VersionNo)
	}
}

func TestUpdateVendorSpecNoAuthCreatesRevision(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "bom",
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 1, UnitPrice: 1000}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}

	spec := localdb.VendorSpec{
		{
			VendorPartnumber: "PN-001",
			Quantity:         2,
			SortOrder:        10,
			LotMappings: []localdb.VendorSpecLotMapping{
				{LotName: "CPU_A", QuantityPerPN: 1},
			},
		},
	}
	if _, err := service.UpdateVendorSpecNoAuth(created.UUID, spec); err != nil {
		t.Fatalf("update vendor spec: %v", err)
	}

	versions := loadVersions(t, local, created.UUID)
	if len(versions) != 2 {
		t.Fatalf("expected 2 versions after vendor spec change, got %d", len(versions))
	}

	cfg, err := local.GetConfigurationByUUID(created.UUID)
	if err != nil {
		t.Fatalf("load config after vendor spec update: %v", err)
	}
	if len(cfg.VendorSpec) != 1 || cfg.VendorSpec[0].VendorPartnumber != "PN-001" {
		t.Fatalf("expected saved vendor spec, got %+v", cfg.VendorSpec)
	}
}

func TestReorderProjectConfigurationsDoesNotCreateNewVersions(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	project := &localdb.LocalProject{
		UUID:          "project-reorder",
		OwnerUsername: "tester",
		Code:          "PRJ-ORDER",
		Variant:       "",
		Name:          ptrString("Project Reorder"),
		IsActive:      true,
		CreatedAt:     time.Now(),
		UpdatedAt:     time.Now(),
		SyncStatus:    "pending",
	}
	if err := local.SaveProject(project); err != nil {
		t.Fatalf("save project: %v", err)
	}

	first, err := service.Create("tester", &CreateConfigRequest{
		Name:        "Cfg A",
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 1, UnitPrice: 100}},
		ServerCount: 1,
		ProjectUUID: &project.UUID,
	})
	if err != nil {
		t.Fatalf("create first config: %v", err)
	}
	second, err := service.Create("tester", &CreateConfigRequest{
		Name:        "Cfg B",
		Items:       models.ConfigItems{{LotName: "CPU_B", Quantity: 1, UnitPrice: 200}},
		ServerCount: 1,
		ProjectUUID: &project.UUID,
	})
	if err != nil {
		t.Fatalf("create second config: %v", err)
	}

	beforeFirst := loadVersions(t, local, first.UUID)
	beforeSecond := loadVersions(t, local, second.UUID)

	reordered, err := service.ReorderProjectConfigurationsNoAuth(project.UUID, []string{second.UUID, first.UUID})
	if err != nil {
		t.Fatalf("reorder configurations: %v", err)
	}
	if len(reordered) != 2 {
		t.Fatalf("expected 2 reordered configs, got %d", len(reordered))
	}
	if reordered[0].UUID != second.UUID || reordered[0].Line != 10 {
		t.Fatalf("expected second config first with line 10, got uuid=%s line=%d", reordered[0].UUID, reordered[0].Line)
	}
	if reordered[1].UUID != first.UUID || reordered[1].Line != 20 {
		t.Fatalf("expected first config second with line 20, got uuid=%s line=%d", reordered[1].UUID, reordered[1].Line)
	}

	afterFirst := loadVersions(t, local, first.UUID)
	afterSecond := loadVersions(t, local, second.UUID)
	if len(afterFirst) != len(beforeFirst) || len(afterSecond) != len(beforeSecond) {
		t.Fatalf("reorder must not create new versions")
	}

	var pendingCount int64
	if err := local.DB().
		Table("pending_changes").
		Where("entity_type = ? AND operation = ? AND entity_uuid IN ?", "configuration", "update", []string{first.UUID, second.UUID}).
		Count(&pendingCount).Error; err != nil {
		t.Fatalf("count reorder pending changes: %v", err)
	}
	if pendingCount < 2 {
		t.Fatalf("expected at least 2 pending update changes for reorder, got %d", pendingCount)
	}
}

func TestAppendOnlyInvariantOldRowsUnchanged(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "initial",
		Items:       models.ConfigItems{{LotName: "SSD_A", Quantity: 1, UnitPrice: 300}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}

	versionsBefore := loadVersions(t, local, created.UUID)
	if len(versionsBefore) != 1 {
		t.Fatalf("expected exactly one version after create")
	}
	v1Before := versionsBefore[0]

	if _, err := service.UpdateNoAuth(created.UUID, &CreateConfigRequest{
		Name:        "initial",
		Items:       models.ConfigItems{{LotName: "SSD_A", Quantity: 2, UnitPrice: 300}},
		ServerCount: 1,
	}); err != nil {
		t.Fatalf("update config: %v", err)
	}
	if _, err := service.RollbackToVersion(created.UUID, 1, "tester"); err != nil {
		t.Fatalf("rollback: %v", err)
	}

	versionsAfter := loadVersions(t, local, created.UUID)
	if len(versionsAfter) != 3 {
		t.Fatalf("expected 3 versions, got %d", len(versionsAfter))
	}
	v1After := versionsAfter[0]

	if v1After.ID != v1Before.ID {
		t.Fatalf("v1 id changed: before=%s after=%s", v1Before.ID, v1After.ID)
	}
	if v1After.Data != v1Before.Data {
		t.Fatalf("v1 data changed")
	}
	if !v1After.CreatedAt.Equal(v1Before.CreatedAt) {
		t.Fatalf("v1 created_at changed")
	}
}

func TestConcurrentSaveNoDuplicateVersionNumbers(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "base",
		Items:       models.ConfigItems{{LotName: "NIC_A", Quantity: 1, UnitPrice: 150}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}

	const workers = 8
	start := make(chan struct{})
	errCh := make(chan error, workers)
	var wg sync.WaitGroup

	for i := 0; i < workers; i++ {
		i := i
		wg.Add(1)
		go func() {
			defer wg.Done()
			<-start
			if err := updateWithRetry(service, created.UUID, i+2); err != nil {
				errCh <- err
			}
		}()
	}

	close(start)
	wg.Wait()
	close(errCh)

	for err := range errCh {
		if err != nil {
			t.Fatalf("concurrent save failed: %v", err)
		}
	}

	type counts struct {
		Total         int64
		DistinctCount int64
		Max           int
	}
	var c counts
	if err := local.DB().Raw(`
SELECT
	COUNT(*) as total,
	COUNT(DISTINCT version_no) as distinct_count,
	COALESCE(MAX(version_no), 0) as max
FROM local_configuration_versions
WHERE configuration_uuid = ?`, created.UUID).Scan(&c).Error; err != nil {
		t.Fatalf("query version counts: %v", err)
	}

	if c.Total != c.DistinctCount {
		t.Fatalf("duplicate version numbers detected: total=%d distinct=%d", c.Total, c.DistinctCount)
	}
	expected := int64(workers + 1) // initial create version + each successful save
	if c.Total != expected || c.Max != int(expected) {
		t.Fatalf("expected total=max=%d, got total=%d max=%d", expected, c.Total, c.Max)
	}
}

func TestUpdateNoAuthKeepsProjectWhenProjectUUIDOmitted(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	project := &localdb.LocalProject{
		UUID:          "project-keep",
		OwnerUsername: "tester",
		Code:          "TEST-KEEP",
		Name:          ptrString("Keep Project"),
		IsActive:      true,
		CreatedAt:     time.Now(),
		UpdatedAt:     time.Now(),
		SyncStatus:    "synced",
	}
	if err := local.SaveProject(project); err != nil {
		t.Fatalf("save project: %v", err)
	}

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "cfg",
		ProjectUUID: &project.UUID,
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 1, UnitPrice: 100}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}
	if created.ProjectUUID == nil || *created.ProjectUUID != project.UUID {
		t.Fatalf("expected created config project_uuid=%s", project.UUID)
	}

	updated, err := service.UpdateNoAuth(created.UUID, &CreateConfigRequest{
		Name:        "cfg-updated",
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 2, UnitPrice: 100}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("update config without project_uuid: %v", err)
	}
	if updated.ProjectUUID == nil || *updated.ProjectUUID != project.UUID {
		t.Fatalf("expected project_uuid to stay %s after update, got %+v", project.UUID, updated.ProjectUUID)
	}
}

func TestUpdateNoAuthAllowsOrphanProjectWhenUUIDUnchanged(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	project := &localdb.LocalProject{
		UUID:          "project-orphan",
		OwnerUsername: "tester",
		Code:          "TEST-ORPHAN",
		Name:          ptrString("Orphan Project"),
		IsActive:      true,
		CreatedAt:     time.Now(),
		UpdatedAt:     time.Now(),
		SyncStatus:    "synced",
	}
	if err := local.SaveProject(project); err != nil {
		t.Fatalf("save project: %v", err)
	}

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "cfg",
		ProjectUUID: &project.UUID,
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 1, UnitPrice: 100}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}

	// Simulate missing project in local cache while config still references its UUID.
	if err := local.DB().Where("uuid = ?", project.UUID).Delete(&localdb.LocalProject{}).Error; err != nil {
		t.Fatalf("delete project: %v", err)
	}

	updated, err := service.UpdateNoAuth(created.UUID, &CreateConfigRequest{
		Name:        "cfg-updated",
		ProjectUUID: &project.UUID,
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 2, UnitPrice: 100}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("update config with orphan project_uuid: %v", err)
	}
	if updated.ProjectUUID == nil || *updated.ProjectUUID != project.UUID {
		t.Fatalf("expected project_uuid to stay %s after update, got %+v", project.UUID, updated.ProjectUUID)
	}
}

func TestUpdateNoAuthRecoversWhenCurrentVersionMissing(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "cfg",
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 1, UnitPrice: 100}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}

	// Simulate corrupted/legacy versioning state:
	// local configuration exists, but all version rows are gone and pointer is stale.
	if err := local.DB().Where("configuration_uuid = ?", created.UUID).
		Delete(&localdb.LocalConfigurationVersion{}).Error; err != nil {
		t.Fatalf("delete versions: %v", err)
	}
	staleID := "missing-version-id"
	if err := local.DB().Model(&localdb.LocalConfiguration{}).
		Where("uuid = ?", created.UUID).
		Update("current_version_id", staleID).Error; err != nil {
		t.Fatalf("set stale current_version_id: %v", err)
	}

	updated, err := service.UpdateNoAuth(created.UUID, &CreateConfigRequest{
		Name:        "cfg-updated",
		Items:       models.ConfigItems{{LotName: "CPU_A", Quantity: 2, UnitPrice: 100}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("update config with missing current version: %v", err)
	}

	if updated.Name != "cfg-updated" {
		t.Fatalf("expected updated name, got %q", updated.Name)
	}

	versions := loadVersions(t, local, created.UUID)
	if len(versions) != 1 {
		t.Fatalf("expected 1 recreated version, got %d", len(versions))
	}
	if versions[0].VersionNo != 1 {
		t.Fatalf("expected recreated version_no=1, got %d", versions[0].VersionNo)
	}
}

func ptrString(value string) *string {
	return &value
}

func newLocalConfigServiceForTest(t *testing.T) (*LocalConfigurationService, *localdb.LocalDB) {
	t.Helper()

	dbPath := filepath.Join(t.TempDir(), "local.db")
	local, err := localdb.New(dbPath)
	if err != nil {
		t.Fatalf("init local db: %v", err)
	}
	t.Cleanup(func() {
		_ = local.Close()
	})

	return NewLocalConfigurationService(
		local,
		syncsvc.NewService(nil, local),
		&QuoteService{},
		func() bool { return false },
	), local
}

func loadVersions(t *testing.T, local *localdb.LocalDB, configurationUUID string) []localdb.LocalConfigurationVersion {
	t.Helper()
	var versions []localdb.LocalConfigurationVersion
	if err := local.DB().
		Where("configuration_uuid = ?", configurationUUID).
		Order("version_no ASC").
		Find(&versions).Error; err != nil {
		t.Fatalf("load versions: %v", err)
	}
	return versions
}

func updateWithRetry(service *LocalConfigurationService, uuid string, quantity int) error {
	var lastErr error
	for i := 0; i < 6; i++ {
		_, err := service.UpdateNoAuth(uuid, &CreateConfigRequest{
			Name:        "base",
			Items:       models.ConfigItems{{LotName: "NIC_A", Quantity: quantity, UnitPrice: 150}},
			ServerCount: 1,
		})
		if err == nil {
			return nil
		}
		lastErr = err
		if errors.Is(err, ErrVersionConflict) || strings.Contains(err.Error(), "database is locked") {
			time.Sleep(10 * time.Millisecond)
			continue
		}
		return err
	}
	return fmt.Errorf("update retries exhausted: %w", lastErr)
}

func TestRollbackVersionSnapshotJSONMatchesV1(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "initial",
		Items:       models.ConfigItems{{LotName: "GPU_A", Quantity: 1, UnitPrice: 2000}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}
	if _, err := service.UpdateNoAuth(created.UUID, &CreateConfigRequest{
		Name:        "initial",
		Items:       models.ConfigItems{{LotName: "GPU_A", Quantity: 2, UnitPrice: 2000}},
		ServerCount: 1,
	}); err != nil {
		t.Fatalf("update: %v", err)
	}
	if _, err := service.RollbackToVersion(created.UUID, 1, "tester"); err != nil {
		t.Fatalf("rollback: %v", err)
	}

	versions := loadVersions(t, local, created.UUID)
	if len(versions) != 3 {
		t.Fatalf("expected 3 versions")
	}

	var v1 map[string]any
	var v3 map[string]any
	if err := json.Unmarshal([]byte(versions[0].Data), &v1); err != nil {
		t.Fatalf("unmarshal v1: %v", err)
	}
	if err := json.Unmarshal([]byte(versions[2].Data), &v3); err != nil {
		t.Fatalf("unmarshal v3: %v", err)
	}
	if fmt.Sprintf("%v", v1["name"]) != fmt.Sprintf("%v", v3["name"]) {
		t.Fatalf("rollback snapshot differs from v1 snapshot by name")
	}
}

func TestDeleteMarksInactiveAndCreatesVersion(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "to-archive",
		Items:       models.ConfigItems{{LotName: "CPU_Z", Quantity: 1, UnitPrice: 500}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}
	if err := service.DeleteNoAuth(created.UUID); err != nil {
		t.Fatalf("delete no auth: %v", err)
	}

	cfg, err := local.GetConfigurationByUUID(created.UUID)
	if err != nil {
		t.Fatalf("load archived config: %v", err)
	}
	if cfg.IsActive {
		t.Fatalf("expected config to be inactive after delete")
	}

	versions := loadVersions(t, local, created.UUID)
	if len(versions) != 2 {
		t.Fatalf("expected 2 versions after archive, got %d", len(versions))
	}
	if versions[1].VersionNo != 2 {
		t.Fatalf("expected archive to create version 2, got %d", versions[1].VersionNo)
	}

	list, total, err := service.ListAll(1, 20)
	if err != nil {
		t.Fatalf("list all: %v", err)
	}
	if total != int64(len(list)) {
		t.Fatalf("unexpected total/list mismatch")
	}
	if len(list) != 0 {
		t.Fatalf("expected archived config to be hidden from list")
	}
}

func TestReactivateRestoresArchivedConfigurationAndCreatesVersion(t *testing.T) {
	service, local := newLocalConfigServiceForTest(t)

	created, err := service.Create("tester", &CreateConfigRequest{
		Name:        "to-reactivate",
		Items:       models.ConfigItems{{LotName: "CPU_R", Quantity: 1, UnitPrice: 700}},
		ServerCount: 1,
	})
	if err != nil {
		t.Fatalf("create config: %v", err)
	}
	if err := service.DeleteNoAuth(created.UUID); err != nil {
		t.Fatalf("archive config: %v", err)
	}
	if _, err := service.ReactivateNoAuth(created.UUID); err != nil {
		t.Fatalf("reactivate config: %v", err)
	}

	cfg, err := local.GetConfigurationByUUID(created.UUID)
	if err != nil {
		t.Fatalf("load reactivated config: %v", err)
	}
	if !cfg.IsActive {
		t.Fatalf("expected config to be active after reactivation")
	}

	versions := loadVersions(t, local, created.UUID)
	if len(versions) != 3 {
		t.Fatalf("expected 3 versions after reactivation, got %d", len(versions))
	}
	if versions[2].VersionNo != 3 {
		t.Fatalf("expected reactivation version 3, got %d", versions[2].VersionNo)
	}

	list, _, err := service.ListAll(1, 20)
	if err != nil {
		t.Fatalf("list all after reactivation: %v", err)
	}
	if len(list) != 1 {
		t.Fatalf("expected reactivated config to be visible in list")
	}
}
