package usecase

import (
	"testing"
)

func TestTemplates_AllPresent(t *testing.T) {
	expected := []string{
		"vendor_check_cloud",
		"sast_dast_audit",
		"dsgvo_quick_check",
		"nis2_readiness",
		"cra_product_check",
	}

	for _, id := range expected {
		if _, ok := Templates[id]; !ok {
			t.Errorf("Template %q missing from Templates map", id)
		}
	}
}

func TestTemplates_HaveQuestions(t *testing.T) {
	for id, tmpl := range Templates {
		if len(tmpl.Questions) == 0 {
			t.Errorf("Template %q has no pre-defined questions", id)
		}
		if tmpl.Name == "" {
			t.Errorf("Template %q has no name", id)
		}
		if len(tmpl.MCFilters) == 0 {
			t.Errorf("Template %q has no MC filters", id)
		}
		if len(tmpl.Regulations) == 0 {
			t.Errorf("Template %q has no regulations", id)
		}
	}
}

func TestTemplates_QuestionIDs_Unique(t *testing.T) {
	for id, tmpl := range Templates {
		seen := make(map[string]bool)
		for _, q := range tmpl.Questions {
			if seen[q.ID] {
				t.Errorf("Template %q has duplicate question ID %q", id, q.ID)
			}
			seen[q.ID] = true
		}
	}
}

func TestTemplateList_ReturnsAll(t *testing.T) {
	list := TemplateList()
	if len(list) != len(Templates) {
		t.Errorf("TemplateList returned %d, expected %d", len(list), len(Templates))
	}
}

func TestDeriveQuestion(t *testing.T) {
	tests := []struct {
		input string
		want  string
	}{
		{"encryption_at_rest", "Ist 'Encryption At Rest' implementiert und dokumentiert?"},
		{"access_control", "Ist 'Access Control' implementiert und dokumentiert?"},
	}

	for _, tt := range tests {
		got := deriveQuestion(tt.input)
		if got != tt.want {
			t.Errorf("deriveQuestion(%q) = %q, want %q", tt.input, got, tt.want)
		}
	}
}

func TestSplitCriteria(t *testing.T) {
	tests := []struct {
		input  string
		expect int
	}{
		{"", 0},
		{"Single criteria", 1},
		{"A | B | C", 3},
		{"A|B", 2},
	}

	for _, tt := range tests {
		got := splitCriteria(tt.input)
		if got == nil && tt.expect == 0 {
			continue
		}
		if len(got) != tt.expect {
			t.Errorf("splitCriteria(%q) returned %d items, want %d", tt.input, len(got), tt.expect)
		}
	}
}

func TestNormalizeSeverity(t *testing.T) {
	tests := []struct {
		input string
		want  string
	}{
		{"HIGH", "HIGH"},
		{"high", "HIGH"},
		{"CRITICAL", "HIGH"},
		{"medium", "MEDIUM"},
		{"LOW", "LOW"},
		{"unknown", "MEDIUM"},
		{"", "MEDIUM"},
	}

	for _, tt := range tests {
		got := normalizeSeverity(tt.input)
		if got != tt.want {
			t.Errorf("normalizeSeverity(%q) = %q, want %q", tt.input, got, tt.want)
		}
	}
}

func TestInferMCSeverity(t *testing.T) {
	tests := []struct {
		name string
		want string
	}{
		{"encryption_at_rest_aes256", "HIGH"},
		{"access_control_mfa", "HIGH"},
		{"incident_response_plan", "HIGH"},
		{"documentation_management", "MEDIUM"},
		{"training_awareness", "MEDIUM"},
	}

	for _, tt := range tests {
		got := inferMCSeverity(tt.name)
		if got != tt.want {
			t.Errorf("inferMCSeverity(%q) = %q, want %q", tt.name, got, tt.want)
		}
	}
}

func TestGenerateFromMC_SmallMC(t *testing.T) {
	mc := MCInfo{
		MasterControlID: "MC-123",
		CanonicalName:   "access_control_basic",
		TotalControls:   3,
		RegSource:       "DSGVO",
	}

	questions := GenerateFromMC(mc)
	if len(questions) != 1 {
		t.Errorf("Expected 1 question for small MC, got %d", len(questions))
	}
	if questions[0].Severity != "HIGH" {
		t.Errorf("Expected HIGH severity for access_control, got %s", questions[0].Severity)
	}
}

func TestGenerateFromMC_MediumMC(t *testing.T) {
	mc := MCInfo{
		MasterControlID: "MC-456",
		CanonicalName:   "documentation_management",
		TotalControls:   8,
		RegSource:       "NIS2",
	}

	questions := GenerateFromMC(mc)
	if len(questions) != 2 {
		t.Errorf("Expected 2 questions for medium MC, got %d", len(questions))
	}
	if questions[1].DependsOn == "" {
		t.Error("Second question should depend on first")
	}
}

func TestGenerateFromMC_LargeMC(t *testing.T) {
	mc := MCInfo{
		MasterControlID: "MC-789",
		CanonicalName:   "risk_management_framework",
		TotalControls:   25,
		RegSource:       "NIS2",
	}

	questions := GenerateFromMC(mc)
	if len(questions) != 3 {
		t.Errorf("Expected 3 questions for large MC, got %d", len(questions))
	}
}
