package training

import (
	"testing"
)

func TestChunkControls_EmptySlice(t *testing.T) {
	chunks := chunkControls(nil, 20)
	if len(chunks) != 0 {
		t.Errorf("expected 0 chunks, got %d", len(chunks))
	}
}

func TestChunkControls_SingleChunk(t *testing.T) {
	controls := make([]CanonicalControlSummary, 5)
	for i := range controls {
		controls[i].ControlID = "CTRL-" + string(rune('A'+i))
	}

	chunks := chunkControls(controls, 20)
	if len(chunks) != 1 {
		t.Errorf("expected 1 chunk, got %d", len(chunks))
	}
	if len(chunks[0]) != 5 {
		t.Errorf("expected 5 controls in chunk, got %d", len(chunks[0]))
	}
}

func TestChunkControls_MultipleChunks(t *testing.T) {
	controls := make([]CanonicalControlSummary, 25)
	for i := range controls {
		controls[i].ControlID = "CTRL-" + string(rune('A'+i%26))
	}

	chunks := chunkControls(controls, 10)
	if len(chunks) != 3 {
		t.Errorf("expected 3 chunks, got %d", len(chunks))
	}
	if len(chunks[0]) != 10 {
		t.Errorf("expected 10 in first chunk, got %d", len(chunks[0]))
	}
	if len(chunks[2]) != 5 {
		t.Errorf("expected 5 in last chunk, got %d", len(chunks[2]))
	}
}

func TestChunkControls_ExactMultiple(t *testing.T) {
	controls := make([]CanonicalControlSummary, 20)
	chunks := chunkControls(controls, 10)
	if len(chunks) != 2 {
		t.Errorf("expected 2 chunks, got %d", len(chunks))
	}
}

func TestBlockGenerator_DeriveRoles_EnterpriseAudience(t *testing.T) {
	bg := &BlockGenerator{}
	controls := []CanonicalControlSummary{
		{ControlID: "AUTH-001", Category: "authentication", TargetAudience: "enterprise"},
	}

	roles := bg.deriveRoles(controls, "enterprise")

	// Should include enterprise mapping roles
	roleSet := map[string]bool{}
	for _, r := range roles {
		roleSet[r] = true
	}

	// Enterprise maps to R1, R4, R5, R6, R7, R9
	if !roleSet[RoleR1] {
		t.Error("expected R1 for enterprise audience")
	}
	if !roleSet[RoleR9] {
		t.Error("expected R9 for enterprise audience")
	}
}

func TestBlockGenerator_DeriveRoles_AuthorityAudience(t *testing.T) {
	bg := &BlockGenerator{}
	controls := []CanonicalControlSummary{
		{ControlID: "GOV-001", Category: "governance", TargetAudience: "authority"},
	}

	roles := bg.deriveRoles(controls, "authority")

	roleSet := map[string]bool{}
	for _, r := range roles {
		roleSet[r] = true
	}

	// Authority maps to R10
	if !roleSet[RoleR10] {
		t.Error("expected R10 for authority audience")
	}
}

func TestBlockGenerator_DeriveRoles_NoFilter(t *testing.T) {
	bg := &BlockGenerator{}
	controls := []CanonicalControlSummary{
		{ControlID: "ENC-001", Category: "encryption", TargetAudience: "provider"},
	}

	roles := bg.deriveRoles(controls, "")

	roleSet := map[string]bool{}
	for _, r := range roles {
		roleSet[r] = true
	}

	// Without audience filter, should use per-control audience + category
	// encryption → R2, R8
	// provider → R2, R8
	if !roleSet[RoleR2] {
		t.Error("expected R2 from encryption category + provider audience")
	}
	if !roleSet[RoleR8] {
		t.Error("expected R8 from encryption category + provider audience")
	}
}

func TestBlockGenerator_DeriveRoles_DefaultToR9(t *testing.T) {
	bg := &BlockGenerator{}
	controls := []CanonicalControlSummary{
		{ControlID: "UNK-001", Category: "", TargetAudience: ""},
	}

	roles := bg.deriveRoles(controls, "")

	if len(roles) != 1 || roles[0] != RoleR9 {
		t.Errorf("expected [R9] default, got %v", roles)
	}
}

func TestBlockGenerator_ExtractControlIDs(t *testing.T) {
	bg := &BlockGenerator{}
	controls := []CanonicalControlSummary{
		{ControlID: "AUTH-001"},
		{ControlID: "AUTH-002"},
		{ControlID: "ENC-010"},
	}

	ids := bg.extractControlIDs(controls)
	if len(ids) != 3 {
		t.Errorf("expected 3 IDs, got %d", len(ids))
	}
	if ids[0] != "AUTH-001" || ids[1] != "AUTH-002" || ids[2] != "ENC-010" {
		t.Errorf("unexpected IDs: %v", ids)
	}
}

func TestBlockGenerator_BuildModuleTitle_SinglePart(t *testing.T) {
	bg := &BlockGenerator{}
	config := &TrainingBlockConfig{Name: "Authentifizierung"}
	controls := []CanonicalControlSummary{{ControlID: "AUTH-001"}}

	title := bg.buildModuleTitle(config, controls, 1, 1)
	if title != "Authentifizierung" {
		t.Errorf("expected 'Authentifizierung', got '%s'", title)
	}
}

func TestBlockGenerator_BuildModuleTitle_MultiPart(t *testing.T) {
	bg := &BlockGenerator{}
	config := &TrainingBlockConfig{Name: "Authentifizierung"}
	controls := []CanonicalControlSummary{{ControlID: "AUTH-001"}}

	title := bg.buildModuleTitle(config, controls, 2, 3)
	expected := "Authentifizierung (Teil 2/3)"
	if title != expected {
		t.Errorf("expected '%s', got '%s'", expected, title)
	}
}

func TestNilIfEmpty(t *testing.T) {
	tests := []struct {
		input    string
		expected bool // true = nil result
	}{
		{"", true},
		{"  ", true},
		{"value", false},
		{" value ", false},
	}

	for _, tt := range tests {
		result := nilIfEmpty(tt.input)
		if tt.expected && result != nil {
			t.Errorf("nilIfEmpty(%q) = %v, expected nil", tt.input, *result)
		}
		if !tt.expected && result == nil {
			t.Errorf("nilIfEmpty(%q) = nil, expected non-nil", tt.input)
		}
	}
}

func TestTargetAudienceRoleMapping_AllKeys(t *testing.T) {
	expectedKeys := []string{"enterprise", "authority", "provider", "all"}
	for _, key := range expectedKeys {
		roles, ok := TargetAudienceRoleMapping[key]
		if !ok {
			t.Errorf("missing key '%s' in TargetAudienceRoleMapping", key)
		}
		if len(roles) == 0 {
			t.Errorf("empty roles for key '%s'", key)
		}
	}
}

func TestCategoryRoleMapping_HasEntries(t *testing.T) {
	if len(CategoryRoleMapping) == 0 {
		t.Error("CategoryRoleMapping is empty")
	}

	// Verify some expected entries
	if _, ok := CategoryRoleMapping["encryption"]; !ok {
		t.Error("missing 'encryption' in CategoryRoleMapping")
	}
	if _, ok := CategoryRoleMapping["authentication"]; !ok {
		t.Error("missing 'authentication' in CategoryRoleMapping")
	}
	if _, ok := CategoryRoleMapping["data_protection"]; !ok {
		t.Error("missing 'data_protection' in CategoryRoleMapping")
	}
}
