package services

import (
	"testing"
	"time"

	"github.com/google/uuid"
	"mgit.msbls.de/m/KanzlAI-mGMT/internal/models"
)

func TestCalculateEndDateAfterDays(t *testing.T) {
	holidays := NewHolidayService(nil)
	calc := NewDeadlineCalculator(holidays)

	eventDate := time.Date(2026, 3, 25, 0, 0, 0, 0, time.UTC) // Wednesday
	timing := "after"
	rule := models.DeadlineRule{
		ID:            uuid.New(),
		Name:          "Test 10 days",
		DurationValue: 10,
		DurationUnit:  "days",
		Timing:        &timing,
	}

	adjusted, original, wasAdjusted := calc.CalculateEndDate(eventDate, rule)

	// 25 March + 10 days = 4 April 2026 (Saturday)
	// Apr 5 = Easter Sunday (holiday), Apr 6 = Easter Monday (holiday) -> adjusted to 7 April (Tuesday)
	expectedOriginal := time.Date(2026, 4, 4, 0, 0, 0, 0, time.UTC)
	expectedAdjusted := time.Date(2026, 4, 7, 0, 0, 0, 0, time.UTC)

	if original != expectedOriginal {
		t.Errorf("original should be %s, got %s", expectedOriginal, original)
	}
	if adjusted != expectedAdjusted {
		t.Errorf("adjusted should be %s, got %s", expectedAdjusted, adjusted)
	}
	if !wasAdjusted {
		t.Error("should have been adjusted (Saturday)")
	}
}

func TestCalculateEndDateBeforeMonths(t *testing.T) {
	holidays := NewHolidayService(nil)
	calc := NewDeadlineCalculator(holidays)

	eventDate := time.Date(2026, 6, 15, 0, 0, 0, 0, time.UTC) // Monday
	timing := "before"
	rule := models.DeadlineRule{
		ID:            uuid.New(),
		Name:          "Test 2 months before",
		DurationValue: 2,
		DurationUnit:  "months",
		Timing:        &timing,
	}

	adjusted, original, wasAdjusted := calc.CalculateEndDate(eventDate, rule)

	// 15 June - 2 months = 15 April 2026 (Wednesday)
	expected := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC)

	if original != expected {
		t.Errorf("original should be %s, got %s", expected, original)
	}
	if adjusted != expected {
		t.Errorf("adjusted should be %s (not a holiday/weekend), got %s", expected, adjusted)
	}
	if wasAdjusted {
		t.Error("should not have been adjusted (Wednesday)")
	}
}

func TestCalculateEndDateWeeks(t *testing.T) {
	holidays := NewHolidayService(nil)
	calc := NewDeadlineCalculator(holidays)

	eventDate := time.Date(2026, 3, 25, 0, 0, 0, 0, time.UTC) // Wednesday
	timing := "after"
	rule := models.DeadlineRule{
		ID:            uuid.New(),
		Name:          "Test 2 weeks",
		DurationValue: 2,
		DurationUnit:  "weeks",
		Timing:        &timing,
	}

	adjusted, original, _ := calc.CalculateEndDate(eventDate, rule)

	// 25 March + 14 days = 8 April 2026 (Wednesday)
	expected := time.Date(2026, 4, 8, 0, 0, 0, 0, time.UTC)
	if original != expected {
		t.Errorf("original should be %s, got %s", expected, original)
	}
	if adjusted != expected {
		t.Errorf("adjusted should be %s, got %s", expected, adjusted)
	}
}

func TestCalculateFromRules(t *testing.T) {
	holidays := NewHolidayService(nil)
	calc := NewDeadlineCalculator(holidays)

	eventDate := time.Date(2026, 3, 25, 0, 0, 0, 0, time.UTC)
	timing := "after"
	code := "TEST-1"

	rules := []models.DeadlineRule{
		{
			ID:            uuid.New(),
			Code:          &code,
			Name:          "Rule A",
			DurationValue: 7,
			DurationUnit:  "days",
			Timing:        &timing,
		},
		{
			ID:            uuid.New(),
			Name:          "Rule B (zero duration)",
			DurationValue: 0,
			DurationUnit:  "days",
		},
	}

	results := calc.CalculateFromRules(eventDate, rules)
	if len(results) != 2 {
		t.Fatalf("expected 2 results, got %d", len(results))
	}

	// Rule A: 25 March + 7 = 1 April (Wednesday)
	if results[0].DueDate != "2026-04-01" {
		t.Errorf("Rule A due date should be 2026-04-01, got %s", results[0].DueDate)
	}
	if results[0].RuleCode != "TEST-1" {
		t.Errorf("Rule A code should be TEST-1, got %s", results[0].RuleCode)
	}

	// Rule B: zero duration -> event date
	if results[1].DueDate != "2026-03-25" {
		t.Errorf("Rule B due date should be 2026-03-25, got %s", results[1].DueDate)
	}
}
