package delivery

import (
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/alertstore/pkg/alert"
)

func TestAckReminderDelayPageLadder(t *testing.T) {
	t.Parallel()

	// page: ack+1h, +2h (gap 1h), +4h (gap 2h), then every 8h.
	require.Equal(t, time.Hour, ackReminderDelay(alert.ClassPage, 0))
	require.Equal(t, time.Hour, ackReminderDelay(alert.ClassPage, 1))
	require.Equal(t, 2*time.Hour, ackReminderDelay(alert.ClassPage, 2))
	require.Equal(t, 8*time.Hour, ackReminderDelay(alert.ClassPage, 3))
	require.Equal(t, 8*time.Hour, ackReminderDelay(alert.ClassPage, 20))
}

func TestAckReminderDelayTicketLadder(t *testing.T) {
	t.Parallel()

	// ticket: ack+4h, +8h (gap 4h), then every 24h.
	require.Equal(t, 4*time.Hour, ackReminderDelay(alert.ClassTicket, 0))
	require.Equal(t, 4*time.Hour, ackReminderDelay(alert.ClassTicket, 1))
	require.Equal(t, 24*time.Hour, ackReminderDelay(alert.ClassTicket, 2))
	require.Equal(t, 24*time.Hour, ackReminderDelay(alert.ClassTicket, 9))
}

func TestAckReminderDelayNeverStopsForAWorkedClass(t *testing.T) {
	t.Parallel()

	// There is no terminal step: the ladder nags until resolve cancels it. A
	// zero here would silently end the chain, so a worked class must never
	// return one.
	for step := 0; step < 100; step++ {
		require.Positive(t, ackReminderDelay(alert.ClassPage, step))
		require.Positive(t, ackReminderDelay(alert.ClassTicket, step))
	}
}

func TestAckReminderDelayZeroForUnworkedClass(t *testing.T) {
	t.Parallel()

	// logging and anything unrecognised are not worked alerts here; a zero delay
	// is how scheduleAckReminder and runAckReminder both learn not to nag.
	require.Zero(t, ackReminderDelay(alert.ClassLogging, 0))
	require.Zero(t, ackReminderDelay("", 0))
}

func TestAckReminderTextCarriesFiringInLanguageNotLogic(t *testing.T) {
	t.Parallel()

	firing := ackReminderText("@him", 4*time.Hour, 3)
	require.Contains(t, firing, "@him")
	require.Contains(t, firing, "4h")
	require.Contains(t, firing, "3 instance(s) are still firing")

	recovered := ackReminderText("@him", 90*time.Minute, 0)
	require.Contains(t, recovered, "All instances have recovered")
	require.Contains(t, recovered, "2h") // 90m rounds to the ladder's hour resolution
}

func TestHumanizeSinceFloorsToOneHour(t *testing.T) {
	t.Parallel()

	require.Equal(t, "1h", humanizeSince(0))
	require.Equal(t, "1h", humanizeSince(20*time.Minute))
	require.Equal(t, "2h", humanizeSince(90*time.Minute))
	require.Equal(t, "8h", humanizeSince(8*time.Hour))
}
