package api

import (
	"strings"
	"testing"
	"time"
)

func airedItem(id, name, availability string, airsAt time.Time) sonarrScheduleItem {
	return sonarrScheduleItem{
		ID:                    id,
		Name:                  name,
		MembyEpisodeCode:      "S02E04",
		MembyEpisodeTitle:     "The Crossing",
		MembyAirsAt:           airsAt.Format(time.RFC3339),
		MembyAvailability:     availability,
		MembyAvailabilityText: availability,
		ImageTags:             map[string]string{"Primary": "sonarr"},
	}
}

func TestBuildSonarrAlertsAnnouncesOnlyEpisodesNotYetInEmby(t *testing.T) {
	location := time.FixedZone("NZST", 12*60*60)
	now := time.Date(2026, 7, 27, 21, 30, 0, 0, location)
	aired := now.Add(-30 * time.Minute)

	alerts := buildSonarrAlerts([]sonarrScheduleItem{
		airedItem("sonarr:7:42", "Northbound", "awaiting", aired),
		airedItem("sonarr:8:43", "Grabbed Show", "downloading", aired.Add(-time.Minute)),
		airedItem("sonarr:9:44", "Already Here", "available", aired),
		airedItem("sonarr:10:45", "Not Watched", "unmonitored", aired),
		airedItem("sonarr:11:46", "Later Tonight", "upcoming", now.Add(90*time.Minute)),
		airedItem("sonarr:12:47", "This Morning", "awaiting", now.Add(-8*time.Hour)),
	}, now, 3*time.Hour)

	if len(alerts) != 2 {
		t.Fatalf("expected 2 alerts, got %d: %+v", len(alerts), alerts)
	}
	first := alerts[0]
	if first.ID != "sonarr:7:42:aired" || first.Kind != alertKindSonarrAired {
		t.Fatalf("unexpected alert identity: %+v", first)
	}
	if first.Title != "Northbound" || first.ItemID != "sonarr:7:42" || first.ImageTag != "sonarr" {
		t.Fatalf("unexpected alert payload: %+v", first)
	}
	if !strings.Contains(first.Message, "S02E04 — The Crossing aired at 9:00 PM") ||
		!strings.Contains(first.Message, "in Emby soon") {
		t.Fatalf("unexpected awaiting message: %q", first.Message)
	}
	if !strings.Contains(alerts[1].Message, "downloading now") {
		t.Fatalf("unexpected downloading message: %q", alerts[1].Message)
	}
}

func TestBuildSonarrAlertsSortsNewestFirstAndCaps(t *testing.T) {
	location := time.FixedZone("NZST", 12*60*60)
	now := time.Date(2026, 7, 27, 22, 0, 0, 0, location)

	items := []sonarrScheduleItem{
		airedItem("sonarr:1:1", "Oldest", "awaiting", now.Add(-100*time.Minute)),
		airedItem("sonarr:2:2", "Newest", "awaiting", now.Add(-5*time.Minute)),
		airedItem("sonarr:3:3", "Middle", "awaiting", now.Add(-40*time.Minute)),
		airedItem("sonarr:4:4", "Older", "awaiting", now.Add(-80*time.Minute)),
	}
	alerts := buildSonarrAlerts(items, now, 3*time.Hour)
	if len(alerts) != maxAlerts {
		t.Fatalf("expected the list capped at %d, got %d", maxAlerts, len(alerts))
	}
	if alerts[0].Title != "Newest" || alerts[1].Title != "Middle" || alerts[2].Title != "Older" {
		t.Fatalf("alerts are not newest-first: %+v", alerts)
	}
}

func TestBuildSonarrAlertsDisabledByZeroWindow(t *testing.T) {
	now := time.Date(2026, 7, 27, 22, 0, 0, 0, time.UTC)
	items := []sonarrScheduleItem{airedItem("sonarr:1:1", "Northbound", "awaiting", now.Add(-time.Minute))}
	if alerts := buildSonarrAlerts(items, now, 0); alerts != nil {
		t.Fatalf("a zero window must disable alerts, got %+v", alerts)
	}
}
