//go:build test

package admin

// Package admin contains tests for admin custom services management endpoints.
//
// Test Coverage:
//   - GetCustomServices: GET /api/admin/custom-services - List all custom services
//   - CreateCustomService: POST /api/admin/custom-services - Create custom service
//   - GetCustomService: GET /api/admin/custom-services/{id} - Get single custom service
//   - UpdateCustomService: PUT /api/admin/custom-services/{id} - Update custom service
//   - PromoteCustomService: POST /api/admin/custom-services/{id}/promote - Promote to regular service
//   - DeleteCustomService: DELETE /api/admin/custom-services/{id} - Delete custom service
//
// Authentication: All endpoints require admin role (403 for non-admins).

import (
	"bytes"
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"crussell/mw"
	"crussell/testutils"
	"crussell/testutils/fixtures"

	"github.com/go-chi/chi/v5"
)

// testAdminID is set by each test after creating an admin user via fixtures,
// so that handlers referencing created_by (which has a FK to users) work correctly.

// makeCustomServiceRequest creates an admin request with chi URL params for custom-services paths.
// Uses testAdminID (must be set by the calling test).
func makeCustomServiceRequest(handler http.Handler, method, path string, body interface{}, adminID string, ctx context.Context) *httptest.ResponseRecorder {
	var req *http.Request
	if body != nil {
		bodyBytes, _ := json.Marshal(body)
		req = httptest.NewRequest(method, path, bytes.NewReader(bodyBytes))
		req.Header.Set("Content-Type", "application/json")
	} else {
		req = httptest.NewRequest(method, path, nil)
	}

	rctx := chi.NewRouteContext()
	if strings.HasPrefix(path, "/api/admin/custom-services/") {
		suffix := path[len("/api/admin/custom-services/"):]
		if slashIdx := strings.Index(suffix, "/"); slashIdx >= 0 {
			rctx.URLParams.Add("id", suffix[:slashIdx])
		} else {
			rctx.URLParams.Add("id", suffix)
		}
	}

	ctx = context.WithValue(ctx, chi.RouteCtxKey, rctx)
	ctx = context.WithValue(ctx, mw.UserIDKey, adminID)
	ctx = context.WithValue(ctx, mw.UserRoleKey, "admin")
	req = req.WithContext(ctx)

	w := httptest.NewRecorder()
	handler.ServeHTTP(w, req)
	return w
}

// =============================================================================
// List Custom Services Tests
// =============================================================================

// TestCustomServices_List verifies that an admin can list all custom services
// with pagination metadata.
func TestCustomServices_List(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	csID1, err := fixtures.CreateTestCustomService(tx)
	if err != nil {
		t.Fatalf("failed to create custom service 1: %v", err)
	}
	defer fixtures.DeleteCustomService(tx, csID1)

	csID2, err := fixtures.CreateTestCustomService(tx)
	if err != nil {
		t.Fatalf("failed to create custom service 2: %v", err)
	}
	defer fixtures.DeleteCustomService(tx, csID2)

	handler := http.HandlerFunc(GetCustomServices)
	w := makeAdminRequest(handler, "GET", "/api/admin/custom-services", nil, ctx)

	if w.Code != http.StatusOK {
		t.Errorf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
	}

	var resp CustomServiceListResponse
	if err := parseResponseBody(w, &resp); err != nil {
		t.Fatalf("failed to parse response: %v", err)
	}

	if resp.Total != 2 {
		t.Errorf("expected total 2, got %d", resp.Total)
	}

	if len(resp.Services) != 2 {
		t.Errorf("expected 2 services, got %d", len(resp.Services))
	}
}

// TestCustomServices_List_Search verifies search filtering via the q parameter,
// including case-insensitive matching and no-results scenarios.
func TestCustomServices_List_Search(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	csID, err := fixtures.CreateTestCustomService(tx)
	if err != nil {
		t.Fatalf("failed to create custom service: %v", err)
	}
	defer fixtures.DeleteCustomService(tx, csID)

	// Set a unique name for search testing
	_, err = tx.Exec(context.Background(),
		"UPDATE custom_services SET name = 'SearchableServiceName' WHERE id = $1", csID)
	if err != nil {
		t.Fatalf("failed to update custom service name: %v", err)
	}

	handler := http.HandlerFunc(GetCustomServices)

	// Matching search (case-insensitive)
	w := makeAdminRequest(handler, "GET", "/api/admin/custom-services?q=searchableservicename", nil, ctx)
	if w.Code != http.StatusOK {
		t.Errorf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
	}

	var resp CustomServiceListResponse
	if err := parseResponseBody(w, &resp); err != nil {
		t.Fatalf("failed to parse response: %v", err)
	}

	if len(resp.Services) != 1 {
		t.Errorf("expected 1 service matching search, got %d", len(resp.Services))
	}

	if resp.Total != 1 {
		t.Errorf("expected total 1, got %d", resp.Total)
	}

	// Non-matching search
	w = makeAdminRequest(handler, "GET", "/api/admin/custom-services?q=NONEXISTENT_QUERY_XYZ", nil, ctx)
	if w.Code != http.StatusOK {
		t.Errorf("expected status 200, got %d", w.Code)
	}

	if err := parseResponseBody(w, &resp); err != nil {
		t.Fatalf("failed to parse response: %v", err)
	}

	if len(resp.Services) != 0 {
		t.Errorf("expected 0 services for non-matching search, got %d", len(resp.Services))
	}

	if resp.Total != 0 {
		t.Errorf("expected total 0, got %d", resp.Total)
	}
}

// TestCustomServices_List_Popular verifies the popular flag returns custom services
// ordered by usage_count, limited to the specified number.
func TestCustomServices_List_Popular(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	csID1, err := fixtures.CreateTestCustomService(tx)
	if err != nil {
		t.Fatalf("failed to create custom service 1: %v", err)
	}
	defer fixtures.DeleteCustomService(tx, csID1)

	csID2, err := fixtures.CreateTestCustomService(tx)
	if err != nil {
		t.Fatalf("failed to create custom service 2: %v", err)
	}
	defer fixtures.DeleteCustomService(tx, csID2)

	// Set usage counts via direct DB to have services with usage_count > 0
	_, err = tx.Exec(context.Background(),
		"UPDATE custom_services SET usage_count = 5, last_used_at = NOW() WHERE id = $1", csID1)
	if err != nil {
		t.Fatalf("failed to set usage count: %v", err)
	}

	handler := http.HandlerFunc(GetCustomServices)
	w := makeAdminRequest(handler, "GET", "/api/admin/custom-services?popular=3", nil, ctx)

	if w.Code != http.StatusOK {
		t.Errorf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
	}

	// Popular mode returns a plain array, not the list response struct
	var services []CustomService
	if err := parseResponseBody(w, &services); err != nil {
		t.Fatalf("failed to parse response: %v", err)
	}

	if len(services) == 0 {
		t.Errorf("expected at least 1 popular service, got 0")
	}

	// Verify the returned service has usage_count > 0
	for _, s := range services {
		if s.UsageCount <= 0 {
			t.Errorf("expected usage_count > 0 for popular service %s, got %d", s.ID, s.UsageCount)
		}
	}
}

// TestCustomServices_List_Pagination verifies page and per_page query parameters.
func TestCustomServices_List_Pagination(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	// Create 3 custom services
	csIDs := make([]string, 3)
	for i := 0; i < 3; i++ {
		csID, err := fixtures.CreateTestCustomService(tx)
		if err != nil {
			t.Fatalf("failed to create custom service %d: %v", i+1, err)
		}
		csIDs[i] = csID
	}
	defer func() {
		for _, id := range csIDs {
			fixtures.DeleteCustomService(tx, id)
		}
	}()

	handler := http.HandlerFunc(GetCustomServices)

	w := makeAdminRequest(handler, "GET", "/api/admin/custom-services?per_page=2", nil, ctx)
	if w.Code != http.StatusOK {
		t.Errorf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
	}

	var resp CustomServiceListResponse
	if err := parseResponseBody(w, &resp); err != nil {
		t.Fatalf("failed to parse response: %v", err)
	}

	if resp.PerPage != 2 {
		t.Errorf("expected per_page 2, got %d", resp.PerPage)
	}

	if resp.Total != 3 {
		t.Errorf("expected total 3, got %d", resp.Total)
	}

	if len(resp.Services) != 2 {
		t.Errorf("expected 2 services on first page, got %d", len(resp.Services))
	}

	if resp.NextCursor == nil {
		t.Fatal("expected next_cursor when items remain")
	}
}

// =============================================================================
// Create Custom Service Tests
// =============================================================================

// TestCustomServices_Create verifies that an admin can create a new custom service
// with name, description, price, duration, minimum age, and notes.
func TestCustomServices_Create(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	handler := http.HandlerFunc(CreateCustomService)

	createReq := CreateCustomServiceRequest{
		Name:               "Custom French Manicure",
		Description:        stringPtr("A custom french manicure service"),
		Price:              45.00,
		DurationMinutes:    60,
		MinimumAgeRequired: 16,
		Notes:              stringPtr("Custom service notes"),
	}

	w := makeRequestWithContext(handler, "POST", "/api/admin/custom-services", createReq, adminID, "admin", ctx)

	if w.Code != http.StatusCreated {
		t.Errorf("expected status 201, got %d. body: %s", w.Code, w.Body.String())
	}

	var cs CustomService
	if err := parseResponseBody(w, &cs); err != nil {
		t.Fatalf("failed to parse response: %v", err)
	}

	if cs.Name != "Custom French Manicure" {
		t.Errorf("expected name 'Custom French Manicure', got %s", cs.Name)
	}

	if cs.Price != 45.00 {
		t.Errorf("expected price 45.00, got %f", cs.Price)
	}

	if cs.DurationMinutes != 60 {
		t.Errorf("expected duration 60, got %d", cs.DurationMinutes)
	}

	if cs.MinimumAgeRequired != 16 {
		t.Errorf("expected minimum_age_required 16, got %d", cs.MinimumAgeRequired)
	}

	if cs.UsageCount != 0 {
		t.Errorf("expected usage_count 0 for new custom service, got %d", cs.UsageCount)
	}

	if cs.ID == "" {
		t.Error("expected non-empty ID for created custom service")
	}
}

// TestCustomServices_Create_Validation verifies that validation errors return
// HTTP 400 for various invalid inputs.
func TestCustomServices_Create_Validation(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	tests := []struct {
		name string
		req  CreateCustomServiceRequest
	}{
		{
			name: "empty name",
			req: CreateCustomServiceRequest{
				Name:            "",
				Price:           50.00,
				DurationMinutes: 60,
			},
		},
		{
			name: "zero price",
			req: CreateCustomServiceRequest{
				Name:            "Test Service",
				Price:           0,
				DurationMinutes: 60,
			},
		},
		{
			name: "negative price",
			req: CreateCustomServiceRequest{
				Name:            "Test Service",
				Price:           -10.00,
				DurationMinutes: 60,
			},
		},
		{
			name: "zero duration",
			req: CreateCustomServiceRequest{
				Name:            "Test Service",
				Price:           50.00,
				DurationMinutes: 0,
			},
		},
		{
			name: "excessive duration",
			req: CreateCustomServiceRequest{
				Name:            "Test Service",
				Price:           50.00,
				DurationMinutes: 481,
			},
		},
		{
			name: "negative minimum age",
			req: CreateCustomServiceRequest{
				Name:               "Test Service",
				Price:              50.00,
				DurationMinutes:    60,
				MinimumAgeRequired: -1,
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			handler := http.HandlerFunc(CreateCustomService)
			w := makeRequestWithContext(handler, "POST", "/api/admin/custom-services", tt.req, adminID, "admin", ctx)

			if w.Code != http.StatusBadRequest {
				t.Errorf("expected status 400, got %d. body: %s", w.Code, w.Body.String())
			}
		})
	}
}

// =============================================================================
// Get Single Custom Service Tests
// =============================================================================

// TestCustomServices_Get verifies that an admin can retrieve a single custom service by ID.
func TestCustomServices_Get(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	csID, err := fixtures.CreateTestCustomService(tx)
	if err != nil {
		t.Fatalf("failed to create custom service: %v", err)
	}
	defer fixtures.DeleteCustomService(tx, csID)

	handler := http.HandlerFunc(GetCustomService)
	w := makeCustomServiceRequest(handler, "GET", "/api/admin/custom-services/"+csID, nil, adminID, ctx)

	if w.Code != http.StatusOK {
		t.Errorf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
	}

	var cs CustomService
	if err := parseResponseBody(w, &cs); err != nil {
		t.Fatalf("failed to parse response: %v", err)
	}

	if cs.ID != csID {
		t.Errorf("expected ID %s, got %s", csID, cs.ID)
	}

	if cs.Name == "" {
		t.Error("expected non-empty name")
	}

	if cs.Price <= 0 {
		t.Errorf("expected positive price, got %f", cs.Price)
	}
}

// TestCustomServices_Get_NotFound verifies that requesting a non-existent custom service returns 404.
func TestCustomServices_Get_NotFound(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	handler := http.HandlerFunc(GetCustomService)
	w := makeCustomServiceRequest(handler, "GET", "/api/admin/custom-services/nonexistent-id", nil, adminID, ctx)

	if w.Code != http.StatusNotFound {
		t.Errorf("expected status 404, got %d. body: %s", w.Code, w.Body.String())
	}
}

// =============================================================================
// Update Custom Service Tests
// =============================================================================

// TestCustomServices_Update verifies that an admin can update a custom service's fields.
func TestCustomServices_Update(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	csID, err := fixtures.CreateTestCustomService(tx)
	if err != nil {
		t.Fatalf("failed to create custom service: %v", err)
	}
	defer fixtures.DeleteCustomService(tx, csID)

	newName := "Updated Custom Name"
	updateReq := UpdateCustomServiceRequest{
		Name: &newName,
	}

	handler := http.HandlerFunc(UpdateCustomService)
	w := makeCustomServiceRequest(handler, "PUT", "/api/admin/custom-services/"+csID, updateReq, adminID, ctx)

	if w.Code != http.StatusOK {
		t.Errorf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
	}

	var resp map[string]string
	if err := parseResponseBody(w, &resp); err != nil {
		t.Fatalf("failed to parse response: %v", err)
	}

	if resp["message"] != "Custom service updated" {
		t.Errorf("expected 'Custom service updated' message, got %s", resp["message"])
	}

	// Verify the update persisted
	var dbName string
	err = tx.QueryRow(context.Background(),
		"SELECT name FROM custom_services WHERE id = $1", csID).Scan(&dbName)
	if err != nil {
		t.Fatalf("failed to query custom service: %v", err)
	}

	if dbName != newName {
		t.Errorf("expected name '%s' in DB, got %s", newName, dbName)
	}
}

// TestCustomServices_Update_NotFound verifies that updating a non-existent custom service returns 404.
func TestCustomServices_Update_NotFound(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	newName := "Updated Name"
	updateReq := UpdateCustomServiceRequest{
		Name: &newName,
	}

	handler := http.HandlerFunc(UpdateCustomService)
	w := makeCustomServiceRequest(handler, "PUT", "/api/admin/custom-services/nonexistent-id", updateReq, adminID, ctx)

	if w.Code != http.StatusNotFound {
		t.Errorf("expected status 404, got %d. body: %s", w.Code, w.Body.String())
	}
}

// TestCustomServices_Update_NoFields verifies that sending an update with no fields
// returns 400 Bad Request.
func TestCustomServices_Update_NoFields(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	csID, err := fixtures.CreateTestCustomService(tx)
	if err != nil {
		t.Fatalf("failed to create custom service: %v", err)
	}
	defer fixtures.DeleteCustomService(tx, csID)

	updateReq := UpdateCustomServiceRequest{}

	handler := http.HandlerFunc(UpdateCustomService)
	w := makeCustomServiceRequest(handler, "PUT", "/api/admin/custom-services/"+csID, updateReq, adminID, ctx)

	if w.Code != http.StatusBadRequest {
		t.Errorf("expected status 400, got %d. body: %s", w.Code, w.Body.String())
	}
}

// =============================================================================
// Promote Custom Service Tests
// =============================================================================

// TestCustomServices_Promote verifies that promoting a custom service creates a
// regular service, migrates data, and deletes the original custom service.
func TestCustomServices_Promote(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	csID, err := fixtures.CreateTestCustomService(tx)
	if err != nil {
		t.Fatalf("failed to create custom service: %v", err)
	}

	handler := http.HandlerFunc(PromoteCustomService)
	w := makeCustomServiceRequest(handler, "POST", "/api/admin/custom-services/"+csID+"/promote", nil, adminID, ctx)

	if w.Code != http.StatusOK {
		t.Errorf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
	}

	var resp map[string]string
	if err := parseResponseBody(w, &resp); err != nil {
		t.Fatalf("failed to parse response: %v", err)
	}

	newServiceID := resp["new_service_id"]
	if newServiceID == "" {
		t.Error("expected non-empty new_service_id in response")
	}

	if resp["custom_service_id"] != csID {
		t.Errorf("expected custom_service_id %s, got %s", csID, resp["custom_service_id"])
	}

	// Verify the custom service was deleted
	var count int
	err = tx.QueryRow(context.Background(),
		"SELECT COUNT(*) FROM custom_services WHERE id = $1", csID).Scan(&count)
	if err != nil {
		t.Fatalf("failed to query custom service: %v", err)
	}
	if count != 0 {
		t.Errorf("expected custom service to be deleted, but it still exists")
	}

	// Verify the new regular service was created
	var serviceName string
	err = tx.QueryRow(context.Background(),
		"SELECT name FROM services WHERE id = $1", newServiceID).Scan(&serviceName)
	if err != nil {
		t.Fatalf("failed to query promoted service: %v", err)
	}
	if serviceName == "" {
		t.Error("expected non-empty service name")
	}

	// Clean up: delete the promoted service
	defer fixtures.DeleteService(tx, newServiceID)
}

// TestCustomServices_Promote_NotFound verifies that promoting a non-existent custom service returns 404.
func TestCustomServices_Promote_NotFound(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	handler := http.HandlerFunc(PromoteCustomService)
	w := makeCustomServiceRequest(handler, "POST", "/api/admin/custom-services/nonexistent-id/promote", nil, adminID, ctx)

	if w.Code != http.StatusNotFound {
		t.Errorf("expected status 404, got %d. body: %s", w.Code, w.Body.String())
	}
}

// =============================================================================
// Delete Custom Service Tests
// =============================================================================

// TestCustomServices_Delete verifies that an admin can delete an unused custom service.
func TestCustomServices_Delete(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	csID, err := fixtures.CreateTestCustomService(tx)
	if err != nil {
		t.Fatalf("failed to create custom service: %v", err)
	}

	handler := http.HandlerFunc(DeleteCustomService)
	w := makeCustomServiceRequest(handler, "DELETE", "/api/admin/custom-services/"+csID, nil, adminID, ctx)

	if w.Code != http.StatusOK {
		t.Errorf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
	}

	var resp map[string]string
	if err := parseResponseBody(w, &resp); err != nil {
		t.Fatalf("failed to parse response: %v", err)
	}

	if resp["message"] != "Custom service deleted" {
		t.Errorf("expected 'Custom service deleted' message, got %s", resp["message"])
	}

	// Verify it's gone from the DB
	var count int
	err = tx.QueryRow(context.Background(),
		"SELECT COUNT(*) FROM custom_services WHERE id = $1", csID).Scan(&count)
	if err != nil {
		t.Fatalf("failed to query custom service: %v", err)
	}
	if count != 0 {
		t.Error("expected custom service to be deleted from database")
	}
}

// TestCustomServices_Delete_NotFound verifies that deleting a non-existent custom service returns 404.
func TestCustomServices_Delete_NotFound(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	handler := http.HandlerFunc(DeleteCustomService)
	w := makeCustomServiceRequest(handler, "DELETE", "/api/admin/custom-services/nonexistent-id", nil, adminID, ctx)

	if w.Code != http.StatusNotFound {
		t.Errorf("expected status 404, got %d. body: %s", w.Code, w.Body.String())
	}
}

// TestCustomServices_Delete_Conflict verifies that deleting a custom service with
// usage_count > 0 returns 409 Conflict.
func TestCustomServices_Delete_Conflict(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	adminID, err := fixtures.CreateTestAdminUser(tx)
	if err != nil {
		t.Fatalf("failed to create admin user: %v", err)
	}
	defer fixtures.DeleteUser(tx, adminID)

	csID, err := fixtures.CreateTestCustomService(tx)
	if err != nil {
		t.Fatalf("failed to create custom service: %v", err)
	}
	defer fixtures.DeleteCustomService(tx, csID)

	// Simulate usage to trigger conflict
	_, err = tx.Exec(context.Background(),
		"UPDATE custom_services SET usage_count = 3 WHERE id = $1", csID)
	if err != nil {
		t.Fatalf("failed to set usage count: %v", err)
	}

	handler := http.HandlerFunc(DeleteCustomService)
	w := makeCustomServiceRequest(handler, "DELETE", "/api/admin/custom-services/"+csID, nil, adminID, ctx)

	if w.Code != http.StatusConflict {
		t.Errorf("expected status 409, got %d. body: %s", w.Code, w.Body.String())
	}
}

// =============================================================================
// Non-Admin Tests
// =============================================================================

// TestCustomServices_NonAdmin verifies that non-admin users receive HTTP 403
// Forbidden when attempting to access any admin custom services endpoint.
func TestCustomServices_NonAdmin(t *testing.T) {
	ctx, tx := testutils.SetupTestTx(t)

	_, err := fixtures.CreateTestUser(tx)
	if err != nil {
		t.Fatalf("failed to create user: %v", err)
	}

	userID, err := fixtures.CreateTestUser(tx)
	if err != nil {
		t.Fatalf("failed to create test user: %v", err)
	}
	defer fixtures.DeleteUser(tx, userID)

	csID, err := fixtures.CreateTestCustomService(tx)
	if err != nil {
		t.Fatalf("failed to create custom service: %v", err)
	}
	defer fixtures.DeleteCustomService(tx, csID)

	// Test LIST
	w := makeUserRequest(mw.RequireAdmin(http.HandlerFunc(GetCustomServices)), "GET", "/api/admin/custom-services", nil, ctx)
	if w.Code != http.StatusForbidden {
		t.Errorf("LIST: expected status 403, got %d", w.Code)
	}

	// Test CREATE
	createReq := CreateCustomServiceRequest{
		Name:            "Test Service",
		Price:           50.00,
		DurationMinutes: 60,
	}
	w = makeUserRequest(mw.RequireAdmin(http.HandlerFunc(CreateCustomService)), "POST", "/api/admin/custom-services", createReq, ctx)
	if w.Code != http.StatusForbidden {
		t.Errorf("CREATE: expected status 403, got %d", w.Code)
	}

	// Test GET
	w = makeUserRequest(mw.RequireAdmin(http.HandlerFunc(GetCustomService)), "GET", "/api/admin/custom-services/"+csID, nil, ctx)
	if w.Code != http.StatusForbidden {
		t.Errorf("GET: expected status 403, got %d", w.Code)
	}

	// Test UPDATE
	updateReq := UpdateCustomServiceRequest{}
	w = makeUserRequest(mw.RequireAdmin(http.HandlerFunc(UpdateCustomService)), "PUT", "/api/admin/custom-services/"+csID, updateReq, ctx)
	if w.Code != http.StatusForbidden {
		t.Errorf("UPDATE: expected status 403, got %d", w.Code)
	}

	// Test PROMOTE
	w = makeUserRequest(mw.RequireAdmin(http.HandlerFunc(PromoteCustomService)), "POST", "/api/admin/custom-services/"+csID+"/promote", nil, ctx)
	if w.Code != http.StatusForbidden {
		t.Errorf("PROMOTE: expected status 403, got %d", w.Code)
	}

	// Test DELETE
	w = makeUserRequest(mw.RequireAdmin(http.HandlerFunc(DeleteCustomService)), "DELETE", "/api/admin/custom-services/"+csID, nil, ctx)
	if w.Code != http.StatusForbidden {
		t.Errorf("DELETE: expected status 403, got %d", w.Code)
	}
}
