package storage

import "testing"

func TestPushSubscriptionLifecycle(t *testing.T) {
	setupTestDB(t)

	if err := AddPushSubscription("sub-1", "https://push.example/ep-a", "p256-a", "auth-a"); err != nil {
		t.Fatal(err)
	}
	// A second endpoint for the same user (e.g. a second device).
	if err := AddPushSubscription("sub-1", "https://push.example/ep-b", "p256-b", "auth-b"); err != nil {
		t.Fatal(err)
	}
	// A different user.
	if err := AddPushSubscription("sub-2", "https://push.example/ep-c", "p256-c", "auth-c"); err != nil {
		t.Fatal(err)
	}

	subs, err := ListPushSubscriptions()
	if err != nil {
		t.Fatal(err)
	}
	if len(subs) != 3 {
		t.Fatalf("got %d subscriptions, want 3", len(subs))
	}

	// Re-subscribing the same endpoint updates keys in place, not a new row.
	if err := AddPushSubscription("sub-1", "https://push.example/ep-a", "p256-a2", "auth-a2"); err != nil {
		t.Fatal(err)
	}
	subs, _ = ListPushSubscriptions()
	if len(subs) != 3 {
		t.Fatalf("after re-subscribe got %d rows, want 3 (upsert, not insert)", len(subs))
	}
	var epA PushSubscription
	for _, s := range subs {
		if s.Endpoint == "https://push.example/ep-a" {
			epA = s
		}
	}
	if epA.P256dh != "p256-a2" || epA.Auth != "auth-a2" {
		t.Errorf("re-subscribe did not refresh keys: %+v", epA)
	}

	if err := RemovePushSubscription("https://push.example/ep-a"); err != nil {
		t.Fatal(err)
	}
	subs, _ = ListPushSubscriptions()
	if len(subs) != 2 {
		t.Fatalf("after remove got %d rows, want 2", len(subs))
	}
}

func TestTouchPushSubscriptionAdvancesWatermark(t *testing.T) {
	setupTestDB(t)
	if err := AddPushSubscription("sub-1", "https://push.example/ep", "p", "a"); err != nil {
		t.Fatal(err)
	}
	subs, _ := ListPushSubscriptions()
	orig := subs[0].LastNotifiedAt

	want := orig + 5000
	if err := TouchPushSubscription("https://push.example/ep", want); err != nil {
		t.Fatal(err)
	}
	subs, _ = ListPushSubscriptions()
	if subs[0].LastNotifiedAt != want {
		t.Errorf("watermark = %d, want %d", subs[0].LastNotifiedAt, want)
	}
}

func TestNewClassifiedSince(t *testing.T) {
	setupTestDB(t)
	now := nowUnix()

	insert := func(guid, headline, source, channel string, classified bool, seenAt int64) {
		if err := InsertStory(&Story{
			GUID: guid, Headline: headline, ArticleURL: "https://x/" + guid,
			Source: source, Channel: channel, Classified: classified, SeenAt: seenAt,
		}); err != nil {
			t.Fatal(err)
		}
	}
	insert("old", "Old news", "Feed A", "tech", true, now-1000)
	insert("fresh1", "Fresh one", "Feed A", "tech", true, now-100)
	insert("fresh2", "Fresh two", "Feed B", "gaming", true, now-50)
	insert("unclassified", "Pending", "Feed A", "", false, now-10)
	insert("discarded", "Junk", "Feed A", "_discarded", true, now-10)

	got, err := NewClassifiedSince(now-500, 10)
	if err != nil {
		t.Fatal(err)
	}
	if len(got) != 2 {
		t.Fatalf("got %d stories, want 2 (fresh classified, non-discarded, after watermark)", len(got))
	}
	// Newest first.
	if got[0].GUID != "" && got[0].Headline != "Fresh two" {
		t.Errorf("first result = %q, want newest 'Fresh two'", got[0].Headline)
	}
	if got[0].Source != "Feed B" || got[1].Source != "Feed A" {
		t.Errorf("unexpected order/sources: %q then %q", got[0].Source, got[1].Source)
	}
}
