package helper

import (
	"testing"
	"time"
)

func TestLoadAsiaManilaLocation(t *testing.T) {
	location, err := LoadAsiaManilaLocation()

	if err != nil {
		t.Errorf("Expected no error, got: %v", err)
	}

	if location == nil {
		t.Fatal("Expected location to not be nil")
	}

	// Check location name
	locationName := location.String()
	if locationName != "Asia/Manila" && locationName != "Local" {
		// "Local" is acceptable as fallback uses FixedZone
		t.Logf("Location name: %s (expected 'Asia/Manila' or 'Local')", locationName)
	}
}

func TestLoadAsiaManilaLocationOffset(t *testing.T) {
	location, err := LoadAsiaManilaLocation()
	if err != nil {
		t.Errorf("Expected no error, got: %v", err)
	}

	// Get current time in Asia/Manila
	now := time.Now().In(location)

	// Asia/Manila is UTC+8 (28800 seconds)
	_, offset := now.Zone()

	expectedOffset := 8 * 60 * 60 // 28800 seconds

	if offset != expectedOffset {
		t.Errorf("Expected offset %d seconds (UTC+8), got %d seconds", expectedOffset, offset)
	}
}

func TestLoadAsiaManilaLocationNotNil(t *testing.T) {
	location, _ := LoadAsiaManilaLocation()

	if location == nil {
		t.Error("Location should never be nil due to fallback")
	}
}

func TestLoadAsiaManilaLocationTimezone(t *testing.T) {
	location, err := LoadAsiaManilaLocation()
	if err != nil {
		t.Errorf("Expected no error, got: %v", err)
	}

	// Create a specific time and check its formatting in Manila timezone
	testTime := time.Date(2025, 1, 1, 12, 0, 0, 0, time.UTC)
	manilaTime := testTime.In(location)

	// Manila is UTC+8, so 12:00 UTC should be 20:00 in Manila
	expectedHour := 20
	if manilaTime.Hour() != expectedHour {
		t.Errorf("Expected hour %d in Manila time, got %d", expectedHour, manilaTime.Hour())
	}
}

func TestLoadAsiaManilaLocationFallback(t *testing.T) {
	// Even if timezone database is not available, function should not panic
	location, err := LoadAsiaManilaLocation()

	if location == nil {
		t.Error("Location should not be nil even with fallback")
	}

	// Error can be nil if LoadLocation succeeds
	// Error is not returned from FixedZone fallback
	if err != nil {
		t.Logf("Note: LoadLocation failed, using fallback: %v", err)
	}
}

func TestLoadAsiaManilaLocationConsistency(t *testing.T) {
	// Call multiple times to ensure consistency
	location1, err1 := LoadAsiaManilaLocation()
	location2, err2 := LoadAsiaManilaLocation()

	if (err1 == nil) != (err2 == nil) {
		t.Error("Inconsistent error returns")
	}

	// Both should have same offset
	now := time.Now()
	time1 := now.In(location1)
	time2 := now.In(location2)

	_, offset1 := time1.Zone()
	_, offset2 := time2.Zone()

	if offset1 != offset2 {
		t.Errorf("Inconsistent offsets: %d vs %d", offset1, offset2)
	}
}

func TestLoadAsiaManilaLocationUTCConversion(t *testing.T) {
	location, _ := LoadAsiaManilaLocation()

	utcTime := time.Date(2025, 6, 15, 10, 30, 0, 0, time.UTC)
	manilaTime := utcTime.In(location)

	// Manila is UTC+8
	expectedHour := 18 // 10 + 8
	if manilaTime.Hour() != expectedHour {
		t.Errorf("Expected hour %d, got %d", expectedHour, manilaTime.Hour())
	}

	// Minute and second should be the same
	if manilaTime.Minute() != 30 {
		t.Errorf("Expected minute 30, got %d", manilaTime.Minute())
	}
}

func TestLoadAsiaManilaLocationDSTHandling(t *testing.T) {
	location, _ := LoadAsiaManilaLocation()

	// Philippines doesn't observe DST, so offset should be constant throughout the year

	// Test summer time
	summerTime := time.Date(2025, 7, 1, 12, 0, 0, 0, location)
	_, summerOffset := summerTime.Zone()

	// Test winter time
	winterTime := time.Date(2025, 1, 1, 12, 0, 0, 0, location)
	_, winterOffset := winterTime.Zone()

	if summerOffset != winterOffset {
		t.Errorf("Philippines should not have DST. Summer offset %d != Winter offset %d", summerOffset, winterOffset)
	}

	// Both should be UTC+8
	expectedOffset := 8 * 60 * 60
	if summerOffset != expectedOffset {
		t.Errorf("Expected offset %d, got %d", expectedOffset, summerOffset)
	}
}

func TestLoadAsiaManilaLocationFormatting(t *testing.T) {
	location, _ := LoadAsiaManilaLocation()

	now := time.Now().In(location)
	formatted := now.Format("2006-01-02 15:04:05 MST")

	if formatted == "" {
		t.Error("Formatted time should not be empty")
	}

	// Should contain timezone information
	if !containsTimeZone(formatted) {
		t.Logf("Formatted time: %s (timezone info may vary)", formatted)
	}
}

func containsTimeZone(s string) bool {
	// Simple check for common timezone formats
	return len(s) > 0
}

func BenchmarkLoadAsiaManilaLocation(b *testing.B) {
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		LoadAsiaManilaLocation()
	}
}

func TestLoadAsiaManilaLocationReusability(t *testing.T) {
	location, _ := LoadAsiaManilaLocation()

	// Use the location multiple times
	for i := 0; i < 100; i++ {
		now := time.Now().In(location)
		if now.Location() != location {
			t.Error("Time location should match provided location")
		}
	}
}
