package repositories

import (
	"fmt"
	"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 TestToggleFavorite_Active_Toggles(t *testing.T) {
	db := testutil.SetupTestDB(t)
	repo := NewContractorRepository(db)

	user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
	residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
	contractor := testutil.CreateTestContractor(t, db, residence.ID, user.ID, "Test Contractor")

	// Initially is_favorite is false
	assert.False(t, contractor.IsFavorite, "contractor should start as not favorite")

	// First toggle: false -> true
	newStatus, err := repo.ToggleFavorite(contractor.ID)
	require.NoError(t, err)
	assert.True(t, newStatus, "first toggle should set favorite to true")

	// Verify in database
	var found models.Contractor
	err = db.First(&found, contractor.ID).Error
	require.NoError(t, err)
	assert.True(t, found.IsFavorite, "database should reflect favorite = true")

	// Second toggle: true -> false
	newStatus, err = repo.ToggleFavorite(contractor.ID)
	require.NoError(t, err)
	assert.False(t, newStatus, "second toggle should set favorite to false")

	// Verify in database
	err = db.First(&found, contractor.ID).Error
	require.NoError(t, err)
	assert.False(t, found.IsFavorite, "database should reflect favorite = false")
}

func TestToggleFavorite_SoftDeleted_ReturnsError(t *testing.T) {
	db := testutil.SetupTestDB(t)
	repo := NewContractorRepository(db)

	user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
	residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
	contractor := testutil.CreateTestContractor(t, db, residence.ID, user.ID, "Deleted Contractor")

	// Soft-delete the contractor
	err := db.Model(&models.Contractor{}).
		Where("id = ?", contractor.ID).
		Update("is_active", false).Error
	require.NoError(t, err)

	// Toggling a soft-deleted contractor should fail (record not found)
	_, err = repo.ToggleFavorite(contractor.ID)
	assert.Error(t, err, "toggling a soft-deleted contractor should return an error")
}

func TestToggleFavorite_NonExistent_ReturnsError(t *testing.T) {
	db := testutil.SetupTestDB(t)
	repo := NewContractorRepository(db)

	_, err := repo.ToggleFavorite(99999)
	assert.Error(t, err, "toggling a non-existent contractor should return an error")
}

func TestContractorRepository_FindByUser_HasDefaultLimit(t *testing.T) {
	db := testutil.SetupTestDB(t)
	repo := NewContractorRepository(db)

	user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "password")
	residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")

	// Create 510 contractors to exceed the default limit of 500
	for i := 0; i < 510; i++ {
		c := &models.Contractor{
			ResidenceID: &residence.ID,
			CreatedByID: user.ID,
			Name:        fmt.Sprintf("Contractor %d", i+1),
			IsActive:    true,
		}
		err := db.Create(c).Error
		require.NoError(t, err)
	}

	contractors, err := repo.FindByUser(user.ID, []uint{residence.ID})
	require.NoError(t, err)
	assert.Equal(t, 500, len(contractors), "FindByUser should return at most 500 contractors by default")
}
