package usecase

import (
	"context"
	"testing"
	"time"

	"haixun-backend/internal/library/clock"
	"haixun-backend/internal/model/job/domain/entity"
	"haixun-backend/internal/model/job/domain/enum"
)

func TestRunMaintenance_EnqueuePendingRetry(t *testing.T) {
	ctx := context.Background()
	template := demoTemplate()
	queue := newMemoryQueueRepo()
	runs := newMemoryRunRepo(nil)
	scheduled := clock.Now().Add(-time.Second).UnixNano()
	runs.run = &entity.Run{
		TemplateType: template.Type,
		Status:       enum.RunStatusPending,
		WorkerType:   "go",
		ScheduledAt:  &scheduled,
	}
	uc := testUseCaseFull(template, runs, nil, queue)

	result, err := uc.RunMaintenance(ctx)
	if err != nil {
		t.Fatalf("RunMaintenance() error = %v", err)
	}
	if result.EnqueuedPending != 1 {
		t.Fatalf("EnqueuedPending = %d, want 1", result.EnqueuedPending)
	}
	if runs.run.Status != enum.RunStatusQueued {
		t.Fatalf("status = %s, want queued", runs.run.Status)
	}
}

func TestRunMaintenance_ReapCancelGrace(t *testing.T) {
	ctx := context.Background()
	template := demoTemplate()
	template.CancelPolicy.GraceSeconds = 1
	queue := newMemoryQueueRepo()
	runs := newMemoryRunRepo(nil)
	cancelAt := clock.Now().Add(-2 * time.Second).UnixNano()
	runs.run = &entity.Run{
		TemplateType:      template.Type,
		Status:            enum.RunStatusCancelRequested,
		CancelRequestedAt: &cancelAt,
		DedupeKey:         "dedupe-1",
	}
	uc := testUseCaseFull(template, runs, nil, queue)

	result, err := uc.RunMaintenance(ctx)
	if err != nil {
		t.Fatalf("RunMaintenance() error = %v", err)
	}
	if result.ReapedCancelGrace != 1 {
		t.Fatalf("ReapedCancelGrace = %d, want 1", result.ReapedCancelGrace)
	}
	if runs.run.Status != enum.RunStatusCancelled {
		t.Fatalf("status = %s, want cancelled", runs.run.Status)
	}
}

func TestRunMaintenance_ReapExpiredLock(t *testing.T) {
	ctx := context.Background()
	template := demoTemplate()
	queue := newMemoryQueueRepo()
	runs := newMemoryRunRepo(nil)
	lockedUntil := clock.Now().Add(-time.Second).UnixNano()
	runs.run = &entity.Run{
		TemplateType: template.Type,
		Status:       enum.RunStatusRunning,
		LockedUntil:  &lockedUntil,
		DedupeKey:    "dedupe-2",
	}
	uc := testUseCaseFull(template, runs, nil, queue)

	result, err := uc.RunMaintenance(ctx)
	if err != nil {
		t.Fatalf("RunMaintenance() error = %v", err)
	}
	if result.ReapedExpiredLocks != 1 {
		t.Fatalf("ReapedExpiredLocks = %d, want 1", result.ReapedExpiredLocks)
	}
	if runs.run.Status != enum.RunStatusExpired {
		t.Fatalf("status = %s, want expired", runs.run.Status)
	}
}
