package repositories import ( "testing" "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 TestDocumentRepository_Create(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := &models.Document{ ResidenceID: residence.ID, CreatedByID: user.ID, Title: "HVAC Warranty", DocumentType: models.DocumentTypeWarranty, FileURL: "https://example.com/hvac.pdf", IsActive: true, } err := repo.Create(doc) require.NoError(t, err) assert.NotZero(t, doc.ID) } func TestDocumentRepository_FindByID(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Test Doc") found, err := repo.FindByID(doc.ID) require.NoError(t, err) assert.Equal(t, doc.ID, found.ID) assert.Equal(t, "Test Doc", found.Title) } func TestDocumentRepository_FindByID_NotFound(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) _, err := repo.FindByID(9999) assert.Error(t, err) } func TestDocumentRepository_FindByID_InactiveNotFound(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Inactive Doc") db.Model(&models.Document{}).Where("id = ?", doc.ID).Update("is_active", false) _, err := repo.FindByID(doc.ID) assert.Error(t, err) } func TestDocumentRepository_FindByResidence(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") otherResidence := testutil.CreateTestResidence(t, db, user.ID, "Other House") testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc A") testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc B") testutil.CreateTestDocument(t, db, otherResidence.ID, user.ID, "Other Doc") docs, err := repo.FindByResidence(residence.ID) require.NoError(t, err) assert.Len(t, docs, 2) } func TestDocumentRepository_FindByResidence_ExcludesInactive(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") active := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Active Doc") inactive := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Inactive Doc") db.Model(&models.Document{}).Where("id = ?", inactive.ID).Update("is_active", false) docs, err := repo.FindByResidence(residence.ID) require.NoError(t, err) assert.Len(t, docs, 1) assert.Equal(t, active.ID, docs[0].ID) } func TestDocumentRepository_FindByUser(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") r1 := testutil.CreateTestResidence(t, db, user.ID, "House 1") r2 := testutil.CreateTestResidence(t, db, user.ID, "House 2") testutil.CreateTestDocument(t, db, r1.ID, user.ID, "Doc 1") testutil.CreateTestDocument(t, db, r2.ID, user.ID, "Doc 2") docs, err := repo.FindByUser([]uint{r1.ID, r2.ID}) require.NoError(t, err) assert.Len(t, docs, 2) } func TestDocumentRepository_Update(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Original Title") doc.Title = "Updated Title" doc.Description = "Updated description" err := repo.Update(doc) require.NoError(t, err) found, err := repo.FindByID(doc.ID) require.NoError(t, err) assert.Equal(t, "Updated Title", found.Title) assert.Equal(t, "Updated description", found.Description) } func TestDocumentRepository_Delete(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "To Delete") err := repo.Delete(doc.ID) require.NoError(t, err) _, err = repo.FindByID(doc.ID) assert.Error(t, err) } func TestDocumentRepository_ActivateDeactivate(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Toggle Doc") // Deactivate err := repo.Deactivate(doc.ID) require.NoError(t, err) _, err = repo.FindByID(doc.ID) assert.Error(t, err) // Not found when inactive // Activate err = repo.Activate(doc.ID) require.NoError(t, err) found, err := repo.FindByID(doc.ID) require.NoError(t, err) assert.Equal(t, doc.ID, found.ID) } func TestDocumentRepository_CountByResidence(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc 1") testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc 2") testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc 3") count, err := repo.CountByResidence(residence.ID) require.NoError(t, err) assert.Equal(t, int64(3), count) } func TestDocumentRepository_CountByResidenceIDs(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") r1 := testutil.CreateTestResidence(t, db, user.ID, "House 1") r2 := testutil.CreateTestResidence(t, db, user.ID, "House 2") testutil.CreateTestDocument(t, db, r1.ID, user.ID, "Doc A") testutil.CreateTestDocument(t, db, r2.ID, user.ID, "Doc B") testutil.CreateTestDocument(t, db, r2.ID, user.ID, "Doc C") count, err := repo.CountByResidenceIDs([]uint{r1.ID, r2.ID}) require.NoError(t, err) assert.Equal(t, int64(3), count) } func TestDocumentRepository_CountByResidenceIDs_Empty(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) count, err := repo.CountByResidenceIDs([]uint{}) require.NoError(t, err) assert.Equal(t, int64(0), count) } func TestDocumentRepository_DocumentImages(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc with Images") // Create image img := &models.DocumentImage{ DocumentID: doc.ID, ImageURL: "https://example.com/img1.jpg", Caption: "Front page", } err := repo.CreateDocumentImage(img) require.NoError(t, err) assert.NotZero(t, img.ID) // Find image by ID found, err := repo.FindImageByID(img.ID) require.NoError(t, err) assert.Equal(t, "https://example.com/img1.jpg", found.ImageURL) assert.Equal(t, "Front page", found.Caption) // Delete single image err = repo.DeleteDocumentImage(img.ID) require.NoError(t, err) _, err = repo.FindImageByID(img.ID) assert.Error(t, err) } func TestDocumentRepository_DeleteDocumentImages(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc with Images") // Create multiple images for i := 0; i < 3; i++ { img := &models.DocumentImage{ DocumentID: doc.ID, ImageURL: "https://example.com/img.jpg", } err := repo.CreateDocumentImage(img) require.NoError(t, err) } // Delete all images for document err := repo.DeleteDocumentImages(doc.ID) require.NoError(t, err) // Verify all deleted var count int64 db.Model(&models.DocumentImage{}).Where("document_id = ?", doc.ID).Count(&count) assert.Equal(t, int64(0), count) } func TestDocumentRepository_FindByIDIncludingInactive(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") doc := testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Deactivated Doc") // Deactivate db.Model(&models.Document{}).Where("id = ?", doc.ID).Update("is_active", false) // FindByID should not find it _, err := repo.FindByID(doc.ID) assert.Error(t, err) // FindByIDIncludingInactive should find it var found models.Document err = repo.FindByIDIncludingInactive(doc.ID, &found) require.NoError(t, err) assert.Equal(t, doc.ID, found.ID) } func TestDocumentRepository_FindByUserFiltered_ByType(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") // Create general document generalDoc := &models.Document{ ResidenceID: residence.ID, CreatedByID: user.ID, Title: "General Doc", DocumentType: models.DocumentTypeGeneral, FileURL: "https://example.com/gen.pdf", IsActive: true, } err := db.Create(generalDoc).Error require.NoError(t, err) // Create warranty document warrantyDoc := &models.Document{ ResidenceID: residence.ID, CreatedByID: user.ID, Title: "Warranty Doc", DocumentType: models.DocumentTypeWarranty, FileURL: "https://example.com/warranty.pdf", IsActive: true, } err = db.Create(warrantyDoc).Error require.NoError(t, err) // Filter by warranty type filter := &DocumentFilter{ DocumentType: string(models.DocumentTypeWarranty), } docs, err := repo.FindByUserFiltered([]uint{residence.ID}, filter) require.NoError(t, err) assert.Len(t, docs, 1) assert.Equal(t, "Warranty Doc", docs[0].Title) } func TestDocumentRepository_FindByUserFiltered_NilFilter(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc 1") testutil.CreateTestDocument(t, db, residence.ID, user.ID, "Doc 2") docs, err := repo.FindByUserFiltered([]uint{residence.ID}, nil) require.NoError(t, err) assert.Len(t, docs, 2) } func TestDocumentRepository_FindWarranties(t *testing.T) { db := testutil.SetupTestDB(t) repo := NewDocumentRepository(db) user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123") residence := testutil.CreateTestResidence(t, db, user.ID, "Test House") // General doc (should not be returned) testutil.CreateTestDocument(t, db, residence.ID, user.ID, "General Doc") // Warranty doc warranty := &models.Document{ ResidenceID: residence.ID, CreatedByID: user.ID, Title: "Warranty", DocumentType: models.DocumentTypeWarranty, FileURL: "https://example.com/warranty.pdf", IsActive: true, } err := db.Create(warranty).Error require.NoError(t, err) docs, err := repo.FindWarranties([]uint{residence.ID}) require.NoError(t, err) assert.Len(t, docs, 1) assert.Equal(t, "Warranty", docs[0].Title) }