package epoch

import (
	"testing"
	"time"

	"github.com/nexuscrm/sentry/internal/config"
)

func TestComputeEpoch(t *testing.T) {
	ref := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
	sched := []config.ResetTime{{Hour: 1, Minute: 0}, {Hour: 10, Minute: 0}}
	tracker := New(sched, ref, 20*time.Minute)

	cases := []struct {
		at     time.Time
		wantID int64
		label  string
	}{
		{time.Date(2026, 1, 1, 0, 30, 0, 0, time.UTC), 0, "before first reset"},
		{time.Date(2026, 1, 1, 1, 0, 0, 0, time.UTC), 1, "at 01:00 day 1"},
		{time.Date(2026, 1, 1, 5, 0, 0, 0, time.UTC), 1, "between resets day 1"},
		{time.Date(2026, 1, 1, 10, 0, 0, 0, time.UTC), 2, "at 10:00 day 1"},
		{time.Date(2026, 1, 2, 0, 30, 0, 0, time.UTC), 2, "day 2 before 01:00"},
		{time.Date(2026, 1, 2, 1, 0, 0, 0, time.UTC), 3, "day 2 01:00"},
	}
	for _, tc := range cases {
		if got := tracker.EpochAt(tc.at); got != tc.wantID {
			t.Errorf("%s (at %v): got %d want %d", tc.label, tc.at, got, tc.wantID)
		}
	}
}

func TestInSuppressionWindow(t *testing.T) {
	ref := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
	sched := []config.ResetTime{{Hour: 1, Minute: 0}}
	tracker := New(sched, ref, 20*time.Minute)

	cases := []struct {
		at   time.Time
		want bool
		lbl  string
	}{
		{time.Date(2026, 1, 1, 0, 59, 0, 0, time.UTC), false, "1 min before"},
		{time.Date(2026, 1, 1, 1, 0, 0, 0, time.UTC), true, "at reset"},
		{time.Date(2026, 1, 1, 1, 10, 0, 0, time.UTC), true, "10 min after"},
		{time.Date(2026, 1, 1, 1, 20, 0, 0, time.UTC), false, "exactly at window end"},
		{time.Date(2026, 1, 1, 1, 30, 0, 0, time.UTC), false, "30 min after"},
	}
	for _, tc := range cases {
		if got := tracker.InSuppressionWindow(tc.at); got != tc.want {
			t.Errorf("%s (at %v): got %v want %v", tc.lbl, tc.at, got, tc.want)
		}
	}
}

func TestNoReset_SingleEpoch(t *testing.T) {
	ref := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
	tracker := New(nil, ref, 20*time.Minute)
	if got := tracker.EpochAt(time.Now()); got != 0 {
		t.Errorf("no-reset mode should stay in epoch 0, got %d", got)
	}
	if tracker.InSuppressionWindow(time.Now()) {
		t.Error("no-reset mode should never be in a suppression window")
	}
}

func TestUnsortedScheduleIsNormalized(t *testing.T) {
	ref := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
	sched := []config.ResetTime{{Hour: 10, Minute: 0}, {Hour: 1, Minute: 0}}
	tracker := New(sched, ref, 20*time.Minute)
	if got := tracker.EpochAt(time.Date(2026, 1, 1, 5, 0, 0, 0, time.UTC)); got != 1 {
		t.Errorf("unsorted schedule: got epoch %d want 1", got)
	}
}
