package eclipse

import (
	"testing"
	"time"

	"b612.me/astro/basic"
)

func TestEclipseSearchStepDoesNotSkipPotentialCandidates(t *testing.T) {
	testCases := []struct {
		name             string
		phaseType        int
		synodicMonthDays float64
		potential        func(float64) bool
	}{
		{
			name:             "solar",
			phaseType:        0,
			synodicMonthDays: solarEclipseSynodicMonthDays,
			potential:        isPotentialSolarEclipse,
		},
		{
			name:             "lunar",
			phaseType:        1,
			synodicMonthDays: lunarEclipseSynodicMonthDays,
			potential:        isPotentialLunarEclipse,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			candidates := eclipseSearchTestCandidates(1600, 800, tc.phaseType, tc.synodicMonthDays)

			for index, candidateTT := range candidates {
				for _, direction := range []int{-1, 1} {
					step := eclipseSearchStep(candidateTT, direction, tc.synodicMonthDays)
					for offset := 1; offset < step; offset++ {
						skippedIndex := index + direction*offset
						if skippedIndex < 0 || skippedIndex >= len(candidates) {
							continue
						}
						if tc.potential(candidates[skippedIndex]) {
							t.Fatalf(
								"%s skip crosses potential candidate: index=%d direction=%d step=%d offset=%d jd=%.8f",
								tc.name,
								index,
								direction,
								step,
								offset,
								candidates[skippedIndex],
							)
						}
					}
				}
			}
		})
	}
}

func eclipseSearchTestCandidates(startYear, years, phaseType int, synodicMonthDays float64) []float64 {
	startTT := basic.Date2JDE(time.Date(startYear, 1, 1, 0, 0, 0, 0, time.UTC))
	endTT := basic.Date2JDE(time.Date(startYear+years, 1, 1, 0, 0, 0, 0, time.UTC))
	candidateTT := basic.CalcMoonSHByJDE(startTT, phaseType)
	candidates := make([]float64, 0, years*13)
	for candidateTT < endTT {
		if candidateTT >= startTT {
			candidates = append(candidates, candidateTT)
		}
		candidateTT = basic.CalcMoonSHByJDE(candidateTT+synodicMonthDays, phaseType)
	}
	return candidates
}
