package services

import (
	"testing"
	"time"
)

func TestCalculateEasterSunday(t *testing.T) {
	tests := []struct {
		year      int
		wantMonth int
		wantDay   int
	}{
		{2024, 3, 31},
		{2025, 4, 20},
		{2026, 4, 5},
		{2027, 3, 28},
	}

	for _, tt := range tests {
		m, d := CalculateEasterSunday(tt.year)
		if m != tt.wantMonth || d != tt.wantDay {
			t.Errorf("CalculateEasterSunday(%d) = %d-%02d, want %d-%02d",
				tt.year, m, d, tt.wantMonth, tt.wantDay)
		}
	}
}

func TestGermanFederalHolidays(t *testing.T) {
	holidays := germanFederalHolidays(2026)

	// Should have 11 federal holidays
	if len(holidays) != 11 {
		t.Fatalf("expected 11 federal holidays, got %d", len(holidays))
	}

	// Check Neujahr
	if holidays[0].Name != "Neujahr" {
		t.Errorf("first holiday should be Neujahr, got %s", holidays[0].Name)
	}
	if holidays[0].Date != time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC) {
		t.Errorf("Neujahr should be Jan 1, got %s", holidays[0].Date)
	}

	// Check Karfreitag 2026 (Easter = Apr 5, so Good Friday = Apr 3)
	found := false
	for _, h := range holidays {
		if h.Name == "Karfreitag" {
			found = true
			expected := time.Date(2026, 4, 3, 0, 0, 0, 0, time.UTC)
			if h.Date != expected {
				t.Errorf("Karfreitag 2026 should be %s, got %s", expected, h.Date)
			}
		}
	}
	if !found {
		t.Error("Karfreitag not found in holidays")
	}
}

func TestHolidayServiceIsNonWorkingDay(t *testing.T) {
	svc := NewHolidayService(nil) // no DB, uses hardcoded holidays

	// Saturday
	sat := time.Date(2026, 3, 28, 0, 0, 0, 0, time.UTC)
	if !svc.IsNonWorkingDay(sat) {
		t.Error("Saturday should be non-working day")
	}

	// Sunday
	sun := time.Date(2026, 3, 29, 0, 0, 0, 0, time.UTC)
	if !svc.IsNonWorkingDay(sun) {
		t.Error("Sunday should be non-working day")
	}

	// Regular Monday
	mon := time.Date(2026, 3, 23, 0, 0, 0, 0, time.UTC)
	if svc.IsNonWorkingDay(mon) {
		t.Error("regular Monday should be a working day")
	}

	// Christmas (Friday Dec 25, 2026)
	xmas := time.Date(2026, 12, 25, 0, 0, 0, 0, time.UTC)
	if !svc.IsNonWorkingDay(xmas) {
		t.Error("Christmas should be non-working day")
	}

	// New Year
	newyear := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
	if !svc.IsNonWorkingDay(newyear) {
		t.Error("New Year should be non-working day")
	}
}

func TestAdjustForNonWorkingDays(t *testing.T) {
	svc := NewHolidayService(nil)

	// Saturday -> Monday
	sat := time.Date(2026, 3, 28, 0, 0, 0, 0, time.UTC)
	adj, orig, adjusted := svc.AdjustForNonWorkingDays(sat)
	if !adjusted {
		t.Error("Saturday should be adjusted")
	}
	if orig != sat {
		t.Error("original should be unchanged")
	}
	expected := time.Date(2026, 3, 30, 0, 0, 0, 0, time.UTC)
	if adj != expected {
		t.Errorf("Saturday should adjust to Monday %s, got %s", expected, adj)
	}

	// Regular Wednesday -> no adjustment
	wed := time.Date(2026, 3, 25, 0, 0, 0, 0, time.UTC)
	adj, _, adjusted = svc.AdjustForNonWorkingDays(wed)
	if adjusted {
		t.Error("Wednesday should not be adjusted")
	}
	if adj != wed {
		t.Error("non-adjusted date should be unchanged")
	}
}
