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 TestTaskTemplateRepository_Create(t *testing.T) {
	db := testutil.SetupTestDB(t)
	testutil.SeedLookupData(t, db)
	repo := NewTaskTemplateRepository(db)

	var cat models.TaskCategory
	require.NoError(t, db.First(&cat).Error)

	var freq models.TaskFrequency
	require.NoError(t, db.First(&freq).Error)

	template := &models.TaskTemplate{
		Title:       "Change HVAC Filter",
		Description: "Replace the HVAC air filter",
		CategoryID:  &cat.ID,
		FrequencyID: &freq.ID,
		IsActive:    true,
		Tags:        "hvac,filter,maintenance",
	}
	err := repo.Create(template)
	require.NoError(t, err)
	assert.NotZero(t, template.ID)
}

func TestTaskTemplateRepository_GetAll(t *testing.T) {
	t.Skip("requires PostgreSQL: SQLite cannot scan jsonb default into json.RawMessage")
	db := testutil.SetupTestDB(t)
	testutil.SeedLookupData(t, db)
	repo := NewTaskTemplateRepository(db)

	// Create active and inactive templates
	t1 := &models.TaskTemplate{Title: "Active Template", IsActive: true}
	t2 := &models.TaskTemplate{Title: "Inactive Template", IsActive: false}
	require.NoError(t, db.Create(t1).Error)
	require.NoError(t, db.Create(t2).Error)

	templates, err := repo.GetAll()
	require.NoError(t, err)
	assert.Len(t, templates, 1) // Only active
	assert.Equal(t, "Active Template", templates[0].Title)
}

func TestTaskTemplateRepository_GetByCategory(t *testing.T) {
	t.Skip("requires PostgreSQL: SQLite cannot scan jsonb default into json.RawMessage")
	db := testutil.SetupTestDB(t)
	testutil.SeedLookupData(t, db)
	repo := NewTaskTemplateRepository(db)

	var cat models.TaskCategory
	require.NoError(t, db.First(&cat).Error)

	t1 := &models.TaskTemplate{Title: "Cat Template", CategoryID: &cat.ID, IsActive: true}
	t2 := &models.TaskTemplate{Title: "No Cat Template", IsActive: true}
	require.NoError(t, db.Create(t1).Error)
	require.NoError(t, db.Create(t2).Error)

	templates, err := repo.GetByCategory(cat.ID)
	require.NoError(t, err)
	assert.Len(t, templates, 1)
	assert.Equal(t, "Cat Template", templates[0].Title)
}

func TestTaskTemplateRepository_Search(t *testing.T) {
	t.Skip("requires PostgreSQL: SQLite cannot scan jsonb default into json.RawMessage")
	db := testutil.SetupTestDB(t)
	repo := NewTaskTemplateRepository(db)

	t1 := &models.TaskTemplate{Title: "Change HVAC Filter", Tags: "hvac,filter", IsActive: true}
	t2 := &models.TaskTemplate{Title: "Fix Faucet", Tags: "plumbing", IsActive: true}
	require.NoError(t, db.Create(t1).Error)
	require.NoError(t, db.Create(t2).Error)

	// Search by title
	results, err := repo.Search("hvac")
	require.NoError(t, err)
	assert.Len(t, results, 1)
	assert.Equal(t, "Change HVAC Filter", results[0].Title)

	// Search by tag
	results, err = repo.Search("plumbing")
	require.NoError(t, err)
	assert.Len(t, results, 1)
	assert.Equal(t, "Fix Faucet", results[0].Title)

	// No match
	results, err = repo.Search("nonexistent")
	require.NoError(t, err)
	assert.Empty(t, results)
}

func TestTaskTemplateRepository_GetByID(t *testing.T) {
	t.Skip("requires PostgreSQL: SQLite cannot scan jsonb default into json.RawMessage")
	db := testutil.SetupTestDB(t)
	repo := NewTaskTemplateRepository(db)

	tmpl := &models.TaskTemplate{Title: "Test Template", IsActive: true}
	require.NoError(t, db.Create(tmpl).Error)

	found, err := repo.GetByID(tmpl.ID)
	require.NoError(t, err)
	assert.Equal(t, "Test Template", found.Title)
}

func TestTaskTemplateRepository_GetByID_NotFound(t *testing.T) {
	db := testutil.SetupTestDB(t)
	repo := NewTaskTemplateRepository(db)

	_, err := repo.GetByID(9999)
	assert.Error(t, err)
}

func TestTaskTemplateRepository_Update(t *testing.T) {
	db := testutil.SetupTestDB(t)
	repo := NewTaskTemplateRepository(db)

	tmpl := &models.TaskTemplate{Title: "Original", IsActive: true}
	require.NoError(t, db.Create(tmpl).Error)

	tmpl.Title = "Updated"
	err := repo.Update(tmpl)
	require.NoError(t, err)

	found, err := repo.GetByID(tmpl.ID)
	require.NoError(t, err)
	assert.Equal(t, "Updated", found.Title)
}

func TestTaskTemplateRepository_Delete(t *testing.T) {
	db := testutil.SetupTestDB(t)
	repo := NewTaskTemplateRepository(db)

	tmpl := &models.TaskTemplate{Title: "To Delete", IsActive: true}
	require.NoError(t, db.Create(tmpl).Error)

	err := repo.Delete(tmpl.ID)
	require.NoError(t, err)

	_, err = repo.GetByID(tmpl.ID)
	assert.Error(t, err)
}

func TestTaskTemplateRepository_GetAllIncludingInactive(t *testing.T) {
	t.Skip("requires PostgreSQL: SQLite cannot scan jsonb default into json.RawMessage")
	db := testutil.SetupTestDB(t)
	repo := NewTaskTemplateRepository(db)

	t1 := &models.TaskTemplate{Title: "Active", IsActive: true}
	t2 := &models.TaskTemplate{Title: "Inactive", IsActive: false}
	require.NoError(t, db.Create(t1).Error)
	require.NoError(t, db.Create(t2).Error)

	templates, err := repo.GetAllIncludingInactive()
	require.NoError(t, err)
	assert.Len(t, templates, 2) // Both active and inactive
}

func TestTaskTemplateRepository_Count(t *testing.T) {
	db := testutil.SetupTestDB(t)
	repo := NewTaskTemplateRepository(db)

	t1 := &models.TaskTemplate{Title: "Active 1", IsActive: true}
	t2 := &models.TaskTemplate{Title: "Active 2", IsActive: true}
	require.NoError(t, db.Create(t1).Error)
	require.NoError(t, db.Create(t2).Error)
	// Use raw SQL for inactive record to avoid GORM default:true overriding IsActive=false
	require.NoError(t, db.Exec(
		"INSERT INTO task_tasktemplate (title, is_active, display_order, created_at, updated_at) VALUES (?, ?, ?, datetime('now'), datetime('now'))",
		"Inactive", false, 0,
	).Error)

	count, err := repo.Count()
	require.NoError(t, err)
	assert.Equal(t, int64(2), count) // Only active
}

func TestTaskTemplateRepository_GetGroupedByCategory(t *testing.T) {
	t.Skip("requires PostgreSQL: SQLite cannot scan jsonb default into json.RawMessage")
	db := testutil.SetupTestDB(t)
	testutil.SeedLookupData(t, db)
	repo := NewTaskTemplateRepository(db)

	var cat models.TaskCategory
	require.NoError(t, db.First(&cat).Error)

	t1 := &models.TaskTemplate{Title: "Categorized", CategoryID: &cat.ID, IsActive: true}
	t2 := &models.TaskTemplate{Title: "Uncategorized", IsActive: true}
	require.NoError(t, db.Create(t1).Error)
	require.NoError(t, db.Create(t2).Error)

	grouped, err := repo.GetGroupedByCategory()
	require.NoError(t, err)
	assert.GreaterOrEqual(t, len(grouped), 2) // At least the category + "Uncategorized"

	// Uncategorized should have the template without category
	assert.Len(t, grouped["Uncategorized"], 1)
	assert.Equal(t, "Uncategorized", grouped["Uncategorized"][0].Title)
}
