package rest_test

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

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

// newDashboardHandler creates a DashboardHandler with a minimal non-nil ServiceManager
func newDashboardHandler() *rest.DashboardHandler {
	return rest.NewDashboardHandler(&services.ServiceManager{})
}

// ---------------------------------------------------------------------------
// DashboardHandler — unauthenticated and validation tests
// ---------------------------------------------------------------------------

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

	handler := newDashboardHandler()
	assert.Panics(t, func() { handler.ListDashboards(c) })
}

func TestDashboardHandler_CreateDashboard_Unauthenticated(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("POST", "/analytics/dashboards", nil)

	handler := newDashboardHandler()
	assert.Panics(t, func() { handler.CreateDashboard(c) })
}

func TestDashboardHandler_CreateDashboard_InvalidJSON(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("POST", "/analytics/dashboards", bytes.NewReader([]byte(`{bad json`)))
	c.Request.Header.Set("Content-Type", "application/json")
	c.Set(constants.ContextKeyUser, auth.UserSession{
		ID:        "user1",
		ProfileId: constants.ProfileSystemAdmin,
	})

	handler := newDashboardHandler()
	handler.CreateDashboard(c)

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

func TestDashboardHandler_CreateDashboard_MissingRequiredFields(t *testing.T) {
	// name and folderId are required
	body := map[string]interface{}{
		"description": "A dashboard",
	}
	bodyBytes, _ := json.Marshal(body)

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

	handler := newDashboardHandler()
	handler.CreateDashboard(c)

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

func TestDashboardHandler_UpdateDashboard_Unauthenticated(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("PATCH", "/analytics/dashboards/dash1", nil)

	handler := newDashboardHandler()
	assert.Panics(t, func() { handler.UpdateDashboard(c) })
}

func TestDashboardHandler_UpdateDashboard_EmptyDashboardID(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("PATCH", "/analytics/dashboards/", nil)
	c.Set(constants.ContextKeyUser, auth.UserSession{
		ID:        "user1",
		ProfileId: constants.ProfileSystemAdmin,
	})
	c.Params = gin.Params{{Key: "dashboardId", Value: ""}}

	handler := newDashboardHandler()
	handler.UpdateDashboard(c)

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

func TestDashboardHandler_UpdateDashboard_EmptyUpdate(t *testing.T) {
	body := map[string]interface{}{}
	bodyBytes, _ := json.Marshal(body)

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

	handler := newDashboardHandler()
	handler.UpdateDashboard(c)

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

func TestDashboardHandler_DeleteDashboard_Unauthenticated(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("DELETE", "/analytics/dashboards/dash1", nil)

	handler := newDashboardHandler()
	assert.Panics(t, func() { handler.DeleteDashboard(c) })
}

func TestDashboardHandler_DeleteDashboard_EmptyDashboardID(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("DELETE", "/analytics/dashboards/", nil)
	c.Set(constants.ContextKeyUser, auth.UserSession{
		ID:        "user1",
		ProfileId: constants.ProfileSystemAdmin,
	})
	c.Params = gin.Params{{Key: "dashboardId", Value: ""}}

	handler := newDashboardHandler()
	handler.DeleteDashboard(c)

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

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

	handler := newDashboardHandler()
	assert.Panics(t, func() { handler.GetDashboardSalesforce(c) })
}

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

	handler := newDashboardHandler()
	handler.GetDashboardSalesforce(c)

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

func TestDashboardHandler_RefreshDashboard_Unauthenticated(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("POST", "/analytics/dashboards/dash1/refresh", nil)

	handler := newDashboardHandler()
	assert.Panics(t, func() { handler.RefreshDashboard(c) })
}

func TestDashboardHandler_RefreshDashboardPUT_Unauthenticated(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("PUT", "/analytics/dashboards/dash1", nil)

	handler := newDashboardHandler()
	assert.Panics(t, func() { handler.RefreshDashboardPUT(c) })
}

func TestDashboardHandler_GetDashboardStatus_Unauthenticated(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest("GET", "/analytics/dashboards/dash1/status", nil)

	handler := newDashboardHandler()
	assert.Panics(t, func() { handler.GetDashboardStatus(c) })
}
