package rest_test

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

	"github.com/gin-gonic/gin"
	"github.com/nexuscrm/backend/internal/interfaces/rest"
	"github.com/nexuscrm/backend/pkg/auth"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// ---------------------------------------------------------------------------
// QuickActionHandler.ListGlobalQuickActions — no service wiring needed
// ---------------------------------------------------------------------------

func TestQuickActionHandler_ListGlobal_Authenticated(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("GET", "/quickActions", nil)
	c.Set(constants.ContextKeyUser, auth.UserSession{
		ID:        "user1",
		ProfileId: constants.ProfileSystemAdmin,
	})

	handler := rest.NewQuickActionHandler(nil)
	handler.ListGlobalQuickActions(c)

	assert.Equal(t, http.StatusOK, w.Code)

	var resp []interface{}
	require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
	assert.Empty(t, resp, "Global quick actions should return empty array per SF spec")
}

func TestQuickActionHandler_ListGlobal_Unauthenticated(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("GET", "/quickActions", nil)

	handler := rest.NewQuickActionHandler(nil)
	assert.Panics(t, func() { handler.ListGlobalQuickActions(c) })
}

// ---------------------------------------------------------------------------
// QuickActionHandler.ListObjectQuickActions — unauthenticated
// ---------------------------------------------------------------------------

func TestQuickActionHandler_ListObject_Unauthenticated(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("GET", "/sobjects/Account/quickActions", nil)
	c.Params = gin.Params{{Key: "sobject", Value: "Account"}}

	handler := rest.NewQuickActionHandler(nil)
	assert.Panics(t, func() { handler.ListObjectQuickActions(c) })
}

// ---------------------------------------------------------------------------
// QuickActionHandler.DescribeQuickAction — returns not found
// ---------------------------------------------------------------------------

func TestQuickActionHandler_Describe_Unauthenticated(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("GET", "/quickActions/NewCase/describe", nil)
	c.Params = gin.Params{{Key: "actionName", Value: "NewCase"}}

	handler := rest.NewQuickActionHandler(nil)
	assert.Panics(t, func() { handler.DescribeQuickAction(c) })
}

func TestQuickActionHandler_Describe_NotImplemented(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("GET", "/quickActions/NewCase/describe", nil)
	c.Params = gin.Params{{Key: "actionName", Value: "NewCase"}}
	c.Set(constants.ContextKeyUser, auth.UserSession{
		ID:        "user1",
		ProfileId: constants.ProfileSystemAdmin,
	})

	handler := rest.NewQuickActionHandler(nil)
	handler.DescribeQuickAction(c)

	assert.Equal(t, http.StatusNotFound, w.Code)

	// SF error responses are arrays
	var resp []map[string]interface{}
	require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
	assert.NotEmpty(t, resp)
}

// ---------------------------------------------------------------------------
// QuickActionHandler.ExecuteQuickAction — validation
// ---------------------------------------------------------------------------

func TestQuickActionHandler_Execute_Unauthenticated(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("POST", "/quickActions/NewCase", nil)
	c.Params = gin.Params{{Key: "actionName", Value: "NewCase"}}

	handler := rest.NewQuickActionHandler(nil)
	assert.Panics(t, func() { handler.ExecuteQuickAction(c) })
}

func TestQuickActionHandler_Execute_InvalidJSON(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("POST", "/quickActions/NewCase", bytes.NewReader([]byte(`{invalid`)))
	c.Request.Header.Set("Content-Type", "application/json")
	c.Params = gin.Params{{Key: "actionName", Value: "NewCase"}}
	c.Set(constants.ContextKeyUser, auth.UserSession{
		ID:        "user1",
		ProfileId: constants.ProfileSystemAdmin,
	})

	handler := rest.NewQuickActionHandler(nil)
	handler.ExecuteQuickAction(c)

	assert.Equal(t, http.StatusBadRequest, w.Code)
}

func TestQuickActionHandler_Execute_NotImplemented(t *testing.T) {
	body := map[string]interface{}{"recordId": "001xxx"}
	bodyBytes, _ := json.Marshal(body)

	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("POST", "/quickActions/NewCase", bytes.NewReader(bodyBytes))
	c.Request.Header.Set("Content-Type", "application/json")
	c.Params = gin.Params{{Key: "actionName", Value: "NewCase"}}
	c.Set(constants.ContextKeyUser, auth.UserSession{
		ID:        "user1",
		ProfileId: constants.ProfileSystemAdmin,
	})

	handler := rest.NewQuickActionHandler(nil)
	handler.ExecuteQuickAction(c)

	assert.Equal(t, http.StatusBadRequest, w.Code)
}
