package repositories import ( "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/treytartt/honeydue-api/internal/models" "github.com/treytartt/honeydue-api/internal/testutil" ) func TestReminderRepository_LogReminder(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewReminderRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof") dueDate := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC) logEntry, err := repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days, nil) require.NoError(t, err) assert.NotZero(t, logEntry.ID) assert.Equal(t, task.ID, logEntry.TaskID) assert.Equal(t, user.ID, logEntry.UserID) assert.Equal(t, models.ReminderStage7Days, logEntry.ReminderStage) } func TestReminderRepository_HasSentReminder(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewReminderRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof") dueDate := time.Date(2026, 4, 15, 12, 30, 0, 0, time.UTC) // Has time component // Not sent yet sent, err := repo.HasSentReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days) require.NoError(t, err) assert.False(t, sent) // Log it _, err = repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days, nil) require.NoError(t, err) // Now should be sent sent, err = repo.HasSentReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days) require.NoError(t, err) assert.True(t, sent) // Different stage should not be sent sent, err = repo.HasSentReminder(task.ID, user.ID, dueDate, models.ReminderStage3Days) require.NoError(t, err) assert.False(t, sent) } func TestReminderRepository_HasSentReminderBatch(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewReminderRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") task1 := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Task 1") task2 := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Task 2") dueDate := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC) // Log reminder for task1 _, err := repo.LogReminder(task1.ID, user.ID, dueDate, models.ReminderStage7Days, nil) require.NoError(t, err) keys := []ReminderKey{ {TaskID: task1.ID, UserID: user.ID, DueDate: dueDate, Stage: models.ReminderStage7Days}, {TaskID: task2.ID, UserID: user.ID, DueDate: dueDate, Stage: models.ReminderStage7Days}, } result, err := repo.HasSentReminderBatch(keys) require.NoError(t, err) assert.True(t, result[0], "task1 reminder should be sent") assert.False(t, result[1], "task2 reminder should not be sent") } func TestReminderRepository_HasSentReminderBatch_Empty(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewReminderRepository(db) result, err := repo.HasSentReminderBatch([]ReminderKey{}) require.NoError(t, err) assert.Empty(t, result) } func TestReminderRepository_GetSentRemindersForTask(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewReminderRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof") dueDate := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC) _, err := repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days, nil) require.NoError(t, err) _, err = repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage3Days, nil) require.NoError(t, err) logs, err := repo.GetSentRemindersForTask(task.ID, user.ID) require.NoError(t, err) assert.Len(t, logs, 2) } func TestReminderRepository_GetSentRemindersForDueDate(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewReminderRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof") dueDate1 := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC) dueDate2 := time.Date(2026, 5, 15, 0, 0, 0, 0, time.UTC) _, err := repo.LogReminder(task.ID, user.ID, dueDate1, models.ReminderStage7Days, nil) require.NoError(t, err) _, err = repo.LogReminder(task.ID, user.ID, dueDate2, models.ReminderStage7Days, nil) require.NoError(t, err) logs, err := repo.GetSentRemindersForDueDate(task.ID, user.ID, dueDate1) require.NoError(t, err) assert.Len(t, logs, 1) } func TestReminderRepository_CleanupOldLogs(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewReminderRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof") // Create old log entry (100 days ago) oldLog := &models.TaskReminderLog{ TaskID: task.ID, UserID: user.ID, DueDate: time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC), ReminderStage: models.ReminderStage7Days, SentAt: time.Now().UTC().AddDate(0, 0, -100), } require.NoError(t, db.Create(oldLog).Error) // Create recent log entry recentLog := &models.TaskReminderLog{ TaskID: task.ID, UserID: user.ID, DueDate: time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC), ReminderStage: models.ReminderStage3Days, SentAt: time.Now().UTC(), } require.NoError(t, db.Create(recentLog).Error) deleted, err := repo.CleanupOldLogs(90) require.NoError(t, err) assert.Equal(t, int64(1), deleted) // Recent log should still exist var count int64 db.Model(&models.TaskReminderLog{}).Count(&count) assert.Equal(t, int64(1), count) } func TestReminderRepository_GetRecentReminderStats(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewReminderRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof") dueDate := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC) // Create recent reminders _, err := repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days, nil) require.NoError(t, err) _, err = repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage3Days, nil) require.NoError(t, err) stats, err := repo.GetRecentReminderStats(24) // last 24 hours require.NoError(t, err) assert.Equal(t, int64(1), stats[string(models.ReminderStage7Days)]) assert.Equal(t, int64(1), stats[string(models.ReminderStage3Days)]) } func TestReminderRepository_LogReminder_WithNotificationID(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewReminderRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") task := testutil.CreateTestTask(t, db, residence.ID, user.ID, "Fix Roof") // Create a notification notif := &models.Notification{ UserID: user.ID, NotificationType: models.NotificationTaskDueSoon, Title: "Test", Body: "Test body", } require.NoError(t, db.Create(notif).Error) dueDate := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC) logEntry, err := repo.LogReminder(task.ID, user.ID, dueDate, models.ReminderStage7Days, ¬if.ID) require.NoError(t, err) assert.NotNil(t, logEntry.NotificationID) assert.Equal(t, notif.ID, *logEntry.NotificationID) }