package ucca

import "testing"

func strPtr(s string) *string { return &s }

func TestMapCompanyProfileToFacts_FullProfile(t *testing.T) {
	profile := &CompanyProfileInput{
		CompanyName:         "Test GmbH",
		LegalForm:           "GmbH",
		Industry:            "Gesundheitswesen",
		EmployeeCount:       "50-249",
		AnnualRevenue:       "10-50 Mio",
		HeadquartersCountry: "DE",
		IsDataController:    true,
		IsDataProcessor:     false,
		UsesAI:              true,
		AIUseCases:          []string{"Diagnostik"},
		DPOName:             strPtr("Dr. Datenschutz"),
		SubjectToNIS2:       true,
		SubjectToAIAct:      true,
	}

	facts := MapCompanyProfileToFacts(profile)

	if facts.Organization.Name != "Test GmbH" {
		t.Errorf("Name: got %q", facts.Organization.Name)
	}
	if facts.Organization.EmployeeCount != 150 {
		t.Errorf("EmployeeCount: got %d, want 150", facts.Organization.EmployeeCount)
	}
	if facts.Organization.AnnualRevenue != 30_000_000 {
		t.Errorf("AnnualRevenue: got %f", facts.Organization.AnnualRevenue)
	}
	if facts.Organization.Country != "DE" {
		t.Errorf("Country: got %q", facts.Organization.Country)
	}
	if !facts.Organization.EUMember {
		t.Error("expected EUMember=true for DE")
	}
	if facts.Sector.PrimarySector != "health" && facts.Sector.PrimarySector != "healthcare" {
		t.Errorf("Sector: got %q, want health or healthcare", facts.Sector.PrimarySector)
	}
	if !facts.DataProtection.IsController {
		t.Error("expected IsController=true")
	}
	if !facts.Personnel.HasDPO {
		t.Error("expected HasDPO=true")
	}
	if !facts.AIUsage.UsesAI {
		t.Error("expected UsesAI=true")
	}
	if !facts.DataProtection.RequiresDSBByLaw {
		t.Error("expected DPO requirement for DE with 150 employees")
	}
}

func TestMapCompanyProfileToFacts_NilProfile(t *testing.T) {
	facts := MapCompanyProfileToFacts(nil)
	if facts == nil {
		t.Fatal("expected non-nil UnifiedFacts for nil profile")
	}
	if facts.Organization.Country != "DE" {
		t.Errorf("expected default country DE, got %q", facts.Organization.Country)
	}
}

func TestParseEmployeeRangeGo(t *testing.T) {
	tests := []struct {
		input    string
		expected int
	}{
		{"1-9", 5},
		{"10-49", 30},
		{"50-249", 150},
		{"250-999", 625},
		{"1000+", 1500},
		{"", 0},
		{"unknown", 0},
	}
	for _, tc := range tests {
		got := parseEmployeeRangeGo(tc.input)
		if got != tc.expected {
			t.Errorf("parseEmployeeRangeGo(%q) = %d, want %d", tc.input, got, tc.expected)
		}
	}
}

func TestParseRevenueRangeGo(t *testing.T) {
	tests := []struct {
		input    string
		expected float64
	}{
		{"< 2 Mio", 1_000_000},
		{"2-10 Mio", 6_000_000},
		{"10-50 Mio", 30_000_000},
		{"50+ Mio", 75_000_000},
		{"", 0},
	}
	for _, tc := range tests {
		got := parseRevenueRangeGo(tc.input)
		if got != tc.expected {
			t.Errorf("parseRevenueRangeGo(%q) = %f, want %f", tc.input, got, tc.expected)
		}
	}
}

func TestMergeCompanyFactsIntoIntakeFacts(t *testing.T) {
	company := NewUnifiedFacts()
	company.Organization.Name = "ACME"
	company.Organization.EmployeeCount = 200
	company.Organization.Country = "DE"
	company.DataProtection.IsController = true
	company.Sector.PrimarySector = "health"

	intake := NewUnifiedFacts()
	intake.DataProtection.ProcessesPersonalData = true
	intake.DataProtection.Profiling = true
	intake.AIUsage.UsesAI = true
	intake.UCCAFacts = &UseCaseIntake{Domain: "hr"}

	merged := MergeCompanyFactsIntoIntakeFacts(company, intake)

	// Company-level fields should come from company
	if merged.Organization.Name != "ACME" {
		t.Errorf("expected company Name, got %q", merged.Organization.Name)
	}
	if merged.Organization.EmployeeCount != 200 {
		t.Errorf("expected company EmployeeCount=200, got %d", merged.Organization.EmployeeCount)
	}
	if merged.Sector.PrimarySector != "health" {
		t.Errorf("expected company sector=health, got %q", merged.Sector.PrimarySector)
	}

	// Use-case-level fields should come from intake
	if !merged.DataProtection.Profiling {
		t.Error("expected intake Profiling=true")
	}
	if !merged.AIUsage.UsesAI {
		t.Error("expected intake UsesAI=true")
	}
	if merged.UCCAFacts == nil || merged.UCCAFacts.Domain != "hr" {
		t.Error("expected intake UCCAFacts preserved")
	}

	// Company-level data protection preserved
	if !merged.DataProtection.IsController {
		t.Error("expected company IsController=true in merged")
	}
}

func TestMergeWithNilCompanyFacts(t *testing.T) {
	intake := NewUnifiedFacts()
	intake.AIUsage.UsesAI = true

	merged := MergeCompanyFactsIntoIntakeFacts(nil, intake)
	if !merged.AIUsage.UsesAI {
		t.Error("expected intake-only merge to preserve AIUsage")
	}
}

func TestNIS2ThresholdTriggered(t *testing.T) {
	profile := &CompanyProfileInput{
		EmployeeCount:       "50-249",
		AnnualRevenue:       "10-50 Mio",
		HeadquartersCountry: "DE",
		Industry:            "Energie",
	}

	facts := MapCompanyProfileToFacts(profile)
	if !facts.Organization.MeetsNIS2SizeThreshold() {
		t.Error("expected NIS2 size threshold met for 150 employees")
	}
}

func TestBDSG_DPOTriggered(t *testing.T) {
	profile := &CompanyProfileInput{
		EmployeeCount:       "10-49",
		HeadquartersCountry: "DE",
		IsDataController:    true,
	}

	facts := MapCompanyProfileToFacts(profile)
	// 30 employees in DE processing personal data → DPO required
	if !facts.DataProtection.RequiresDSBByLaw {
		t.Error("expected BDSG DPO requirement for 30 employees in DE")
	}
}

func TestBDSG_DPONotTriggeredSmallCompany(t *testing.T) {
	profile := &CompanyProfileInput{
		EmployeeCount:       "1-9",
		HeadquartersCountry: "DE",
		IsDataController:    true,
	}

	facts := MapCompanyProfileToFacts(profile)
	// 5 employees → DPO NOT required
	if facts.DataProtection.RequiresDSBByLaw {
		t.Error("expected no DPO requirement for 5 employees")
	}
}

func TestComputeEnrichmentHints_AllMissing(t *testing.T) {
	profile := &CompanyProfileInput{}
	hints := ComputeEnrichmentHints(profile)
	if len(hints) < 4 {
		t.Errorf("expected at least 4 hints for empty profile, got %d", len(hints))
	}
	// Check high priority hints
	highCount := 0
	for _, h := range hints {
		if h.Priority == "high" {
			highCount++
		}
	}
	if highCount < 3 {
		t.Errorf("expected at least 3 high-priority hints, got %d", highCount)
	}
}

func TestComputeEnrichmentHints_Complete(t *testing.T) {
	profile := &CompanyProfileInput{
		EmployeeCount:       "50-249",
		AnnualRevenue:       "10-50 Mio",
		Industry:            "IT",
		HeadquartersCountry: "DE",
		DPOName:             strPtr("Max Mustermann"),
	}
	hints := ComputeEnrichmentHints(profile)
	if len(hints) != 0 {
		t.Errorf("expected 0 hints for complete profile, got %d: %+v", len(hints), hints)
	}
}

func TestComputeEnrichmentHints_NilProfile(t *testing.T) {
	hints := ComputeEnrichmentHints(nil)
	if len(hints) < 4 {
		t.Errorf("expected all critical hints for nil profile, got %d", len(hints))
	}
}

func TestIsEUCountry(t *testing.T) {
	if !isEUCountry("DE") {
		t.Error("DE should be EU")
	}
	if !isEUCountry("at") {
		t.Error("AT should be EU (case insensitive)")
	}
	if isEUCountry("US") {
		t.Error("US should not be EU")
	}
	if isEUCountry("CH") {
		t.Error("CH should not be EU")
	}
}

func TestBuildCompanyContext(t *testing.T) {
	profile := &CompanyProfileInput{
		EmployeeCount:       "250-999",
		AnnualRevenue:       "50+ Mio",
		HeadquartersCountry: "DE",
		Industry:            "Finanzdienstleistungen",
		SubjectToNIS2:       true,
	}

	ctx := BuildCompanyContext(profile)
	if ctx == nil {
		t.Fatal("expected non-nil context")
	}
	if ctx.Country != "DE" {
		t.Errorf("Country: got %q", ctx.Country)
	}
	if !ctx.NIS2Applicable {
		t.Error("expected NIS2 applicable")
	}
	if !ctx.DPORequired {
		t.Error("expected DPO required for large DE company")
	}
}
