package utils

import (
	"testing"
)

func TestParseFilenameTimestamps(t *testing.T) {
	t.Run("should parse YYMMDD format (test case a)", func(t *testing.T) {
		filenames := []string{
			"201012_123456.wav",
			"201014_123456.WAV",
			"201217_123456.wav",
			"211122_123456.WAV",
		}

		results, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		if len(results) != 4 {
			t.Fatalf("Expected 4 results, got %d", len(results))
		}

		// Year 20 should be interpreted as 2020 (less variance than days)
		if results[0].Timestamp.Year() != 2020 {
			t.Errorf("Year incorrect for file 0: got %d, want 2020", results[0].Timestamp.Year())
		}
		if results[0].Timestamp.Month() != 10 { // October
			t.Errorf("Month incorrect for file 0: got %d, want 10", results[0].Timestamp.Month())
		}
		if results[0].Timestamp.Day() != 12 {
			t.Errorf("Day incorrect for file 0: got %d, want 12", results[0].Timestamp.Day())
		}
		if results[0].Timestamp.Hour() != 12 {
			t.Errorf("Hour incorrect for file 0: got %d, want 12", results[0].Timestamp.Hour())
		}
		if results[0].Timestamp.Minute() != 34 {
			t.Errorf("Minute incorrect for file 0: got %d, want 34", results[0].Timestamp.Minute())
		}
		if results[0].Timestamp.Second() != 56 {
			t.Errorf("Second incorrect for file 0: got %d, want 56", results[0].Timestamp.Second())
		}

		if results[3].Timestamp.Year() != 2021 {
			t.Errorf("Year incorrect for file 3: got %d, want 2021", results[3].Timestamp.Year())
		}
		if results[3].Timestamp.Month() != 11 { // November
			t.Errorf("Month incorrect for file 3: got %d, want 11", results[3].Timestamp.Month())
		}
		if results[3].Timestamp.Day() != 22 {
			t.Errorf("Day incorrect for file 3: got %d, want 22", results[3].Timestamp.Day())
		}
	})

	t.Run("should parse DDMMYY format (test case b)", func(t *testing.T) {
		filenames := []string{
			"121020_123456.WAV",
			"141020_123456.wav",
			"171220_123456.WAV",
			"221121_123456.wav",
		}

		results, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		if len(results) != 4 {
			t.Fatalf("Expected 4 results, got %d", len(results))
		}

		// More variance in first two digits (12,14,17,22) than last two (20,20,20,21)
		// So DDMMYY format: day=first, month=middle, year=last+2000
		if results[0].Timestamp.Day() != 12 {
			t.Errorf("Day incorrect for file 0: got %d, want 12", results[0].Timestamp.Day())
		}
		if results[0].Timestamp.Month() != 10 { // October
			t.Errorf("Month incorrect for file 0: got %d, want 10", results[0].Timestamp.Month())
		}
		if results[0].Timestamp.Year() != 2020 {
			t.Errorf("Year incorrect for file 0: got %d, want 2020", results[0].Timestamp.Year())
		}

		if results[2].Timestamp.Day() != 17 {
			t.Errorf("Day incorrect for file 2: got %d, want 17", results[2].Timestamp.Day())
		}
		if results[2].Timestamp.Month() != 12 { // December
			t.Errorf("Month incorrect for file 2: got %d, want 12", results[2].Timestamp.Month())
		}
		if results[2].Timestamp.Year() != 2020 {
			t.Errorf("Year incorrect for file 2: got %d, want 2020", results[2].Timestamp.Year())
		}
	})

	t.Run("should parse YYYYMMDD format (test case c)", func(t *testing.T) {
		filenames := []string{
			"20230609_103000.WAV",
			"20241109_201504.wav",
		}

		results, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		if len(results) != 2 {
			t.Fatalf("Expected 2 results, got %d", len(results))
		}

		if results[0].Timestamp.Year() != 2023 {
			t.Errorf("Year incorrect: got %d, want 2023", results[0].Timestamp.Year())
		}
		if results[0].Timestamp.Month() != 6 { // June
			t.Errorf("Month incorrect: got %d, want 6", results[0].Timestamp.Month())
		}
		if results[0].Timestamp.Day() != 9 {
			t.Errorf("Day incorrect: got %d, want 9", results[0].Timestamp.Day())
		}
		if results[0].Timestamp.Hour() != 10 {
			t.Errorf("Hour incorrect: got %d, want 10", results[0].Timestamp.Hour())
		}
		if results[0].Timestamp.Minute() != 30 {
			t.Errorf("Minute incorrect: got %d, want 30", results[0].Timestamp.Minute())
		}
		if results[0].Timestamp.Second() != 0 {
			t.Errorf("Second incorrect: got %d, want 0", results[0].Timestamp.Second())
		}

		if results[1].Timestamp.Year() != 2024 {
			t.Errorf("Year incorrect: got %d, want 2024", results[1].Timestamp.Year())
		}
	})

	t.Run("should parse mixed 6-digit dates with variance detection (test case d)", func(t *testing.T) {
		filenames := []string{
			"120119_003002.wav",
			"180120_231502.wav",
			"170122_010005.wav",
			"010419_234502.WAV",
			"310320_231502.wav",
			"220824_231502.WAV",
			"240123_231502.wav",
		}

		results, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		if len(results) != 7 {
			t.Fatalf("Expected 7 results, got %d", len(results))
		}

		// First two digits: 12,18,17,01,31,22,24 (variance = high)
		// Last two digits: 19,20,22,19,20,24,23 (variance = lower)
		// Should be DDMMYY format
		if results[0].Timestamp.Day() != 12 {
			t.Errorf("Day incorrect: got %d, want 12", results[0].Timestamp.Day())
		}
		if results[0].Timestamp.Month() != 1 { // January
			t.Errorf("Month incorrect: got %d, want 1", results[0].Timestamp.Month())
		}
		if results[0].Timestamp.Year() != 2019 {
			t.Errorf("Year incorrect: got %d, want 2019", results[0].Timestamp.Year())
		}

		if results[4].Timestamp.Day() != 31 {
			t.Errorf("Day incorrect for file 4: got %d, want 31", results[4].Timestamp.Day())
		}
		if results[4].Timestamp.Month() != 3 { // March
			t.Errorf("Month incorrect for file 4: got %d, want 3", results[4].Timestamp.Month())
		}
	})

	t.Run("should throw error for empty filename array", func(t *testing.T) {
		_, err := ParseFilenameTimestamps([]string{})
		if err == nil {
			t.Error("Expected error for empty filename array")
		}
		if err != nil && err.Error() != "no filenames provided" {
			t.Logf("Error message: %v", err)
		}
	})

	t.Run("should throw error for filenames without date patterns", func(t *testing.T) {
		_, err := ParseFilenameTimestamps([]string{"invalid_filename.wav"})
		if err == nil {
			t.Error("Expected error for filenames without date patterns")
		}
	})

	t.Run("should parse filenames with prefixes (test case e)", func(t *testing.T) {
		filenames := []string{
			"XYZ123_7689_20230609_103000.WAV",
			"string 20241109_201504.wav",
		}

		results, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		if len(results) != 2 {
			t.Fatalf("Expected 2 results, got %d", len(results))
		}

		if results[0].Timestamp.Year() != 2023 {
			t.Errorf("Year incorrect: got %d, want 2023", results[0].Timestamp.Year())
		}
		if results[0].Timestamp.Month() != 6 { // June
			t.Errorf("Month incorrect: got %d, want 6", results[0].Timestamp.Month())
		}
		if results[0].Timestamp.Day() != 9 {
			t.Errorf("Day incorrect: got %d, want 9", results[0].Timestamp.Day())
		}
		if results[0].Timestamp.Hour() != 10 {
			t.Errorf("Hour incorrect: got %d, want 10", results[0].Timestamp.Hour())
		}
		if results[0].Timestamp.Minute() != 30 {
			t.Errorf("Minute incorrect: got %d, want 30", results[0].Timestamp.Minute())
		}
		if results[0].Timestamp.Second() != 0 {
			t.Errorf("Second incorrect: got %d, want 0", results[0].Timestamp.Second())
		}

		if results[1].Timestamp.Year() != 2024 {
			t.Errorf("Year incorrect: got %d, want 2024", results[1].Timestamp.Year())
		}
		if results[1].Timestamp.Month() != 11 { // November
			t.Errorf("Month incorrect: got %d, want 11", results[1].Timestamp.Month())
		}
		if results[1].Timestamp.Day() != 9 {
			t.Errorf("Day incorrect: got %d, want 9", results[1].Timestamp.Day())
		}
		if results[1].Timestamp.Hour() != 20 {
			t.Errorf("Hour incorrect: got %d, want 20", results[1].Timestamp.Hour())
		}
		if results[1].Timestamp.Minute() != 15 {
			t.Errorf("Minute incorrect: got %d, want 15", results[1].Timestamp.Minute())
		}
		if results[1].Timestamp.Second() != 4 {
			t.Errorf("Second incorrect: got %d, want 4", results[1].Timestamp.Second())
		}
	})

	t.Run("should parse filenames with complex prefixes (test case f)", func(t *testing.T) {
		filenames := []string{
			"abcdefg__1234_180120_231502.wav",
			"string 120119_003002.wav",
			"ABCD EFG___170122_010005.wav",
			"BHD_1234 010419_234502.WAV",
			"cill xyz 310320_231502.wav",
			"220824_231502.WAV",
			"240123_231502.wav",
		}

		results, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		if len(results) != 7 {
			t.Fatalf("Expected 7 results, got %d", len(results))
		}

		// Same pattern as test case d - should be DDMMYY
		if results[0].Timestamp.Day() != 18 {
			t.Errorf("Day incorrect: got %d, want 18", results[0].Timestamp.Day())
		}
		if results[0].Timestamp.Month() != 1 { // January
			t.Errorf("Month incorrect: got %d, want 1", results[0].Timestamp.Month())
		}
		if results[0].Timestamp.Year() != 2020 {
			t.Errorf("Year incorrect: got %d, want 2020", results[0].Timestamp.Year())
		}
		if results[0].Timestamp.Hour() != 23 {
			t.Errorf("Hour incorrect: got %d, want 23", results[0].Timestamp.Hour())
		}
		if results[0].Timestamp.Minute() != 15 {
			t.Errorf("Minute incorrect: got %d, want 15", results[0].Timestamp.Minute())
		}
		if results[0].Timestamp.Second() != 2 {
			t.Errorf("Second incorrect: got %d, want 2", results[0].Timestamp.Second())
		}

		if results[1].Timestamp.Day() != 12 {
			t.Errorf("Day incorrect: got %d, want 12", results[1].Timestamp.Day())
		}
		if results[1].Timestamp.Month() != 1 { // January
			t.Errorf("Month incorrect: got %d, want 1", results[1].Timestamp.Month())
		}
		if results[1].Timestamp.Year() != 2019 {
			t.Errorf("Year incorrect: got %d, want 2019", results[1].Timestamp.Year())
		}

		if results[4].Timestamp.Day() != 31 {
			t.Errorf("Day incorrect: got %d, want 31", results[4].Timestamp.Day())
		}
		if results[4].Timestamp.Month() != 3 { // March
			t.Errorf("Month incorrect: got %d, want 3", results[4].Timestamp.Month())
		}
		if results[4].Timestamp.Year() != 2020 {
			t.Errorf("Year incorrect: got %d, want 2020", results[4].Timestamp.Year())
		}
	})

	t.Run("should throw error for mixed date formats", func(t *testing.T) {
		mixedFormats := []string{"201012_123456.wav", "20231012_123456.wav"} // 6-digit vs 8-digit
		_, err := ParseFilenameTimestamps(mixedFormats)
		if err == nil {
			t.Error("Expected error for mixed date formats")
		}
	})

	t.Run("should throw error for wrong length patterns", func(t *testing.T) {
		wrongLength := []string{"2010_123456.wav"} // 4 digits instead of 6 or 8
		_, err := ParseFilenameTimestamps(wrongLength)
		if err == nil {
			t.Error("Expected error for wrong length patterns")
		}
	})

	t.Run("should throw error when not enough files for 6-digit disambiguation", func(t *testing.T) {
		singleFile := []string{"120119_003002.wav"}
		_, err := ParseFilenameTimestamps(singleFile)
		if err == nil {
			t.Error("Expected error when not enough files for 6-digit disambiguation")
		}
	})
}

func TestApplyTimezoneOffset(t *testing.T) {
	t.Run("should apply UTC timezone correctly", func(t *testing.T) {
		filenames := []string{
			"201012_123456.wav",
			"201014_123456.WAV",
		}

		parsed, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		results, err := ApplyTimezoneOffset(parsed, "UTC")
		if err != nil {
			t.Fatalf("Failed to apply timezone: %v", err)
		}

		if len(results) != 2 {
			t.Fatalf("Expected 2 results, got %d", len(results))
		}

		// Check timezone offset is +00:00
		_, offset := results[0].Zone()
		if offset != 0 {
			t.Errorf("UTC offset should be 0, got %d", offset)
		}
	})

	t.Run("should use fixed offset for entire cluster spanning DST transition", func(t *testing.T) {
		// Test files spanning the Auckland DST transition in April 2021
		// DST ended on April 4, 2021 (UTC+13 -> UTC+12)
		filenames := []string{
			"20210401_120000.wav", // April 1st - DST still active (UTC+13)
			"20210410_120000.wav", // April 10th - DST ended (would be UTC+12 if DST applied)
			"20210420_120000.wav", // April 20th - Standard time (would be UTC+12 if DST applied)
		}

		parsed, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		results, err := ApplyTimezoneOffset(parsed, "Pacific/Auckland")
		if err != nil {
			t.Fatalf("Failed to apply timezone: %v", err)
		}

		if len(results) != 3 {
			t.Fatalf("Expected 3 results, got %d", len(results))
		}

		// All files should use the same offset (from April 1st - earliest file)
		offsets := make([]int, len(results))
		for i, r := range results {
			_, offset := r.Zone()
			offsets[i] = offset
		}

		// Check all offsets are the same
		firstOffset := offsets[0]
		for i, offset := range offsets {
			if offset != firstOffset {
				t.Errorf("File %d has different offset: got %d, want %d", i, offset, firstOffset)
			}
		}

		// The offset should be UTC+13 (from the earliest file: April 1st)
		expectedOffsetSeconds := 13 * 3600
		if firstOffset != expectedOffsetSeconds {
			t.Errorf("Offset incorrect: got %d seconds, want %d seconds (UTC+13)", firstOffset, expectedOffsetSeconds)
		}

		// Verify UTC conversion uses the fixed offset consistently
		// All files at 12:00 local should convert to the same UTC hour (with UTC+13 offset)
		// 12:00 Auckland time - 13 hours = 23:00 UTC previous day
		for i, utcTime := range results {
			utc := utcTime.UTC()
			if utc.Hour() != 23 {
				t.Errorf("File %d UTC hour incorrect: got %d, want 23", i, utc.Hour())
			}
		}
	})

	t.Run("should handle out-of-order filenames correctly", func(t *testing.T) {
		// Files not in chronological order - should still use earliest file for offset
		filenames := []string{
			"20210410_120000.wav", // April 10th (later)
			"20210401_120000.wav", // April 1st (earliest - should determine offset)
			"20210405_120000.wav", // April 5th (middle)
		}

		parsed, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		results, err := ApplyTimezoneOffset(parsed, "Pacific/Auckland")
		if err != nil {
			t.Fatalf("Failed to apply timezone: %v", err)
		}

		// All files should use UTC+13 offset (from April 1st, the earliest)
		for i, r := range results {
			_, offset := r.Zone()
			expectedOffset := 13 * 3600
			if offset != expectedOffset {
				t.Errorf("File %d offset incorrect: got %d, want %d", i, offset, expectedOffset)
			}
		}

		// Results should maintain original filename order
		if results[0].Day() != 10 {
			t.Errorf("Result 0 should be April 10th, got day %d", results[0].Day())
		}
		if results[1].Day() != 1 {
			t.Errorf("Result 1 should be April 1st, got day %d", results[1].Day())
		}
		if results[2].Day() != 5 {
			t.Errorf("Result 2 should be April 5th, got day %d", results[2].Day())
		}
	})

	t.Run("should apply fixed offset consistently across large time spans", func(t *testing.T) {
		// Test files spanning multiple months with different DST periods
		filenames := []string{
			"20210215_120000.wav", // February 15th (summer, UTC+13)
			"20210615_120000.wav", // June 15th (winter, would be UTC+12 if DST applied)
			"20210815_120000.wav", // August 15th (winter, would be UTC+12 if DST applied)
		}

		parsed, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		results, err := ApplyTimezoneOffset(parsed, "Pacific/Auckland")
		if err != nil {
			t.Fatalf("Failed to apply timezone: %v", err)
		}

		// All files should use the same offset from the earliest file (February)
		expectedOffset := 13 * 3600
		for i, r := range results {
			_, offset := r.Zone()
			if offset != expectedOffset {
				t.Errorf("File %d offset incorrect: got %d, want %d", i, offset, expectedOffset)
			}
		}

		// Verify UTC conversion is consistent with fixed offset
		for i, r := range results {
			utc := r.UTC()
			if utc.Hour() != 23 { // 12 - 13 = -1 hour (23:00 previous day)
				t.Errorf("File %d UTC hour incorrect: got %d, want 23", i, utc.Hour())
			}
		}
	})

	t.Run("should handle US DST transitions with fixed offset", func(t *testing.T) {
		// Test US spring DST transition (March 14, 2021)
		filenames := []string{
			"20210310_120000.wav", // March 10th - before DST (UTC-5)
			"20210320_120000.wav", // March 20th - after DST (would be UTC-4 if DST applied)
		}

		parsed, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		results, err := ApplyTimezoneOffset(parsed, "America/New_York")
		if err != nil {
			t.Fatalf("Failed to apply timezone: %v", err)
		}

		// All files should use the same offset from earliest file (March 10th)
		expectedOffset := -5 * 3600
		for i, r := range results {
			_, offset := r.Zone()
			if offset != expectedOffset {
				t.Errorf("File %d offset incorrect: got %d, want %d", i, offset, expectedOffset)
			}
		}

		// Verify UTC conversion uses fixed offset
		for i, r := range results {
			utc := r.UTC()
			if utc.Hour() != 17 { // 12 + 5 = 17
				t.Errorf("File %d UTC hour incorrect: got %d, want 17", i, utc.Hour())
			}
		}
	})

	t.Run("should handle empty timestamps array", func(t *testing.T) {
		_, err := ApplyTimezoneOffset([]FilenameTimestamp{}, "UTC")
		if err == nil {
			t.Error("Expected error for empty timestamps array")
		}
	})

	t.Run("should handle invalid timezone", func(t *testing.T) {
		filenames := []string{"20210401_120000.wav"}
		parsed, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		_, err = ApplyTimezoneOffset(parsed, "Invalid/Timezone")
		if err == nil {
			t.Error("Expected error for invalid timezone")
		}
	})
}

func TestHasTimestampFilename(t *testing.T) {
	testCases := []struct {
		filename string
		expected bool
	}{
		{"201012_123456.wav", true},
		{"20230609_103000.WAV", true},
		{"invalid_filename.wav", false},
		{"201012_123456.txt", false},
		{"201012.wav", false},
		{"_123456.wav", false},
		{"", false},
	}

	for _, tc := range testCases {
		t.Run(tc.filename, func(t *testing.T) {
			result := HasTimestampFilename(tc.filename)
			if result != tc.expected {
				t.Errorf("HasTimestampFilename(%q) = %v, want %v", tc.filename, result, tc.expected)
			}
		})
	}
}

func TestFilenameParserEdgeCases(t *testing.T) {
	t.Run("should handle case-insensitive file extensions", func(t *testing.T) {
		filenames := []string{
			"201012_123456.wav",
			"201014_123456.WAV",
			"201217_123456.Wav",
		}

		results, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		if len(results) != 3 {
			t.Errorf("Expected 3 results, got %d", len(results))
		}
	})

	t.Run("should validate invalid dates", func(t *testing.T) {
		// 32nd day doesn't exist - should be caught by validation
		filenames := []string{"20240132_120000.wav"}

		_, err := ParseFilenameTimestamps(filenames)
		if err == nil {
			t.Error("Expected error for invalid date (day 32)")
		}
	})

	t.Run("should validate invalid months", func(t *testing.T) {
		// 13th month doesn't exist
		filenames := []string{"20241301_120000.wav"}

		_, err := ParseFilenameTimestamps(filenames)
		if err == nil {
			t.Error("Expected error for invalid month (13)")
		}
	})

	t.Run("should handle February 29th in leap year", func(t *testing.T) {
		filenames := []string{"20240229_120000.wav"} // 2024 is a leap year

		results, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse leap year date: %v", err)
		}

		if results[0].Timestamp.Day() != 29 {
			t.Errorf("Expected day 29, got %d", results[0].Timestamp.Day())
		}
	})

	t.Run("should reject February 29th in non-leap year", func(t *testing.T) {
		filenames := []string{"20230229_120000.wav"} // 2023 is not a leap year

		_, err := ParseFilenameTimestamps(filenames)
		if err == nil {
			t.Error("Expected error for Feb 29th in non-leap year")
		}
	})
}

func TestUTCConversionCorrectness(t *testing.T) {
	t.Run("should convert Pacific/Auckland night recordings correctly to UTC", func(t *testing.T) {
		// Test a night recording: 21:00 (9 PM) Pacific/Auckland
		// In May 2021, Pacific/Auckland is UTC+12 (standard time)
		// So 21:00 Pacific/Auckland should become 09:00 UTC same day
		filenames := []string{"20210505_210000.wav"}

		parsed, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		results, err := ApplyTimezoneOffset(parsed, "Pacific/Auckland")
		if err != nil {
			t.Fatalf("Failed to apply timezone: %v", err)
		}

		utcDate := results[0].UTC()
		if utcDate.Year() != 2021 {
			t.Errorf("Year incorrect: got %d, want 2021", utcDate.Year())
		}
		if utcDate.Month() != 5 {
			t.Errorf("Month incorrect: got %d, want 5", utcDate.Month())
		}
		if utcDate.Day() != 5 {
			t.Errorf("Day incorrect: got %d, want 5 (same day)", utcDate.Day())
		}
		if utcDate.Hour() != 9 {
			t.Errorf("Hour incorrect: got %d, want 9 (21 - 12 = 9)", utcDate.Hour())
		}
	})

	t.Run("should convert day recordings correctly to UTC", func(t *testing.T) {
		// Test a day recording: 12:00 (noon) Pacific/Auckland
		// Should become 00:00 UTC same day (midnight)
		filenames := []string{"20210505_120000.wav"}

		parsed, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		results, err := ApplyTimezoneOffset(parsed, "Pacific/Auckland")
		if err != nil {
			t.Fatalf("Failed to apply timezone: %v", err)
		}

		utcDate := results[0].UTC()
		if utcDate.Hour() != 0 {
			t.Errorf("Hour incorrect: got %d, want 0 (12 - 12 = 0, midnight UTC)", utcDate.Hour())
		}
		if utcDate.Day() != 5 {
			t.Errorf("Day incorrect: got %d, want 5 (same day)", utcDate.Day())
		}
	})

	t.Run("should handle date rollover correctly", func(t *testing.T) {
		// Test early morning: 02:00 Pacific/Auckland
		// Should become 14:00 UTC previous day
		filenames := []string{"20210505_020000.wav"}

		parsed, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		results, err := ApplyTimezoneOffset(parsed, "Pacific/Auckland")
		if err != nil {
			t.Fatalf("Failed to apply timezone: %v", err)
		}

		utcDate := results[0].UTC()
		if utcDate.Day() != 4 {
			t.Errorf("Day incorrect: got %d, want 4 (previous day)", utcDate.Day())
		}
		if utcDate.Hour() != 14 {
			t.Errorf("Hour incorrect: got %d, want 14 (2 - 12 = -10, so previous day 14:00)", utcDate.Hour())
		}
	})

	t.Run("should convert correctly for negative offset timezone", func(t *testing.T) {
		// Test 15:00 (3 PM) New York in June (UTC-4 during DST)
		// Should become 19:00 UTC same day
		filenames := []string{"20210615_150000.wav"}

		parsed, err := ParseFilenameTimestamps(filenames)
		if err != nil {
			t.Fatalf("Failed to parse filenames: %v", err)
		}

		results, err := ApplyTimezoneOffset(parsed, "America/New_York")
		if err != nil {
			t.Fatalf("Failed to apply timezone: %v", err)
		}

		utcDate := results[0].UTC()
		if utcDate.Hour() != 19 {
			t.Errorf("Hour incorrect: got %d, want 19 (15 + 4 = 19)", utcDate.Hour())
		}
		if utcDate.Day() != 15 {
			t.Errorf("Day incorrect: got %d, want 15 (same day)", utcDate.Day())
		}
	})
}