package usecase

import (
	"context"
	"testing"

	"haixun-backend/internal/model/job/domain/entity"
	"haixun-backend/internal/model/job/domain/enum"
	domusecase "haixun-backend/internal/model/job/domain/usecase"
)

func TestCreateRun_BlocksNonRepeatableAfterSuccess(t *testing.T) {
	ctx := context.Background()
	template := demoTemplate()
	template.Repeatable = false
	template.DedupeKeys = []string{"scope_id"}

	runs := newMemoryRunRepo(nil)
	queue := newMemoryQueueRepo()
	uc := testUseCaseFull(template, runs, nil, queue)

	first, err := uc.CreateRun(ctx, domusecase.CreateRunRequest{
		TemplateType: template.Type,
		Scope:        "user",
		ScopeID:      "u1",
	})
	if err != nil {
		t.Fatalf("first CreateRun() error = %v", err)
	}
	first.Status = enum.RunStatusSucceeded
	first.DedupeKey = buildDedupeKey(template, "user", "u1", nil)
	_, _ = runs.Update(ctx, first)

	_, err = uc.CreateRun(ctx, domusecase.CreateRunRequest{
		TemplateType: template.Type,
		Scope:        "user",
		ScopeID:      "u1",
	})
	if err == nil {
		t.Fatal("expected duplicate completed job error")
	}
}

func TestCreateRun_DedupeLeaseBlocksParallel(t *testing.T) {
	ctx := context.Background()
	template := demoTemplate()
	template.Repeatable = true
	template.DedupeKeys = []string{"scope_id"}

	queue := newMemoryQueueRepo()
	uc := testUseCaseFull(template, newMemoryRunRepo(nil), nil, queue)

	first, err := uc.CreateRun(ctx, domusecase.CreateRunRequest{
		TemplateType: template.Type,
		Scope:        "user",
		ScopeID:      "u1",
	})
	if err != nil {
		t.Fatalf("first CreateRun() error = %v", err)
	}
	if first.Status != enum.RunStatusQueued {
		t.Fatalf("first status = %s, want queued", first.Status)
	}

	_, err = uc.CreateRun(ctx, domusecase.CreateRunRequest{
		TemplateType: template.Type,
		Scope:        "user",
		ScopeID:      "u1",
	})
	if err == nil {
		t.Fatal("expected in-progress dedupe error")
	}
}

func TestBuildDedupeKey_IncludesScopeID(t *testing.T) {
	template := &entity.Template{
		Type:       "demo",
		DedupeKeys: []string{"scope_id", "target"},
	}
	key1 := buildDedupeKey(template, "user", "a", map[string]any{"target": "x"})
	key2 := buildDedupeKey(template, "user", "b", map[string]any{"target": "x"})
	if key1 == key2 {
		t.Fatal("dedupe keys should differ by scope_id")
	}
}
