package middleware

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/QuantumNous/new-api/setting/system_setting"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
)

func TestSyncAuth_Disabled(t *testing.T) {
	gin.SetMode(gin.TestMode)
	router := gin.New()
	router.Use(SyncAuth())
	router.GET("/test", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"success": true})
	})

	// 未启用区域同步
	settings := system_setting.GetRegionSyncSettings()
	settings.Enabled = false

	req, _ := http.NewRequest("GET", "/test", nil)
	req.Header.Set("X-Sync-API-Key", "test-key")
	req.Header.Set("X-Sync-Node", "slave-1")

	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusForbidden, w.Code)
	assert.Contains(t, w.Body.String(), "region sync is not enabled")
}

func TestSyncAuth_MissingAPIKey(t *testing.T) {
	gin.SetMode(gin.TestMode)
	router := gin.New()
	router.Use(SyncAuth())
	router.GET("/test", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"success": true})
	})

	settings := system_setting.GetRegionSyncSettings()
	settings.Enabled = true
	settings.SyncApiKey = "test-key"

	req, _ := http.NewRequest("GET", "/test", nil)
	req.Header.Set("X-Sync-Node", "slave-1")

	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusUnauthorized, w.Code)
	assert.Contains(t, w.Body.String(), "missing sync API key")
}

func TestSyncAuth_InvalidAPIKey(t *testing.T) {
	gin.SetMode(gin.TestMode)
	router := gin.New()
	router.Use(SyncAuth())
	router.GET("/test", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"success": true})
	})

	settings := system_setting.GetRegionSyncSettings()
	settings.Enabled = true
	settings.SyncApiKey = "correct-key"

	req, _ := http.NewRequest("GET", "/test", nil)
	req.Header.Set("X-Sync-API-Key", "wrong-key")
	req.Header.Set("X-Sync-Node", "slave-1")

	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusUnauthorized, w.Code)
	assert.Contains(t, w.Body.String(), "invalid sync API key")
}

func TestSyncAuth_MissingNode(t *testing.T) {
	gin.SetMode(gin.TestMode)
	router := gin.New()
	router.Use(SyncAuth())
	router.GET("/test", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"success": true})
	})

	settings := system_setting.GetRegionSyncSettings()
	settings.Enabled = true
	settings.SyncApiKey = "test-key"

	req, _ := http.NewRequest("GET", "/test", nil)
	req.Header.Set("X-Sync-API-Key", "test-key")

	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusBadRequest, w.Code)
	assert.Contains(t, w.Body.String(), "missing sync node identifier")
}

func TestSyncAuth_Valid(t *testing.T) {
	gin.SetMode(gin.TestMode)
	router := gin.New()
	router.Use(SyncAuth())
	router.GET("/test", func(c *gin.Context) {
		node := GetSyncNode(c)
		c.JSON(http.StatusOK, gin.H{
			"success": true,
			"node":    node,
		})
	})

	settings := system_setting.GetRegionSyncSettings()
	settings.Enabled = true
	settings.SyncApiKey = "test-key"

	req, _ := http.NewRequest("GET", "/test", nil)
	req.Header.Set("X-Sync-API-Key", "test-key")
	req.Header.Set("X-Sync-Node", "slave-1")

	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code)
	assert.Contains(t, w.Body.String(), "slave-1")
}

func TestValidateSyncAPIKey_Single(t *testing.T) {
	assert.True(t, validateSyncAPIKey("test-key", "test-key"))
	assert.False(t, validateSyncAPIKey("test-key", "different-key"))
	assert.False(t, validateSyncAPIKey("", ""))
}

func TestValidateSyncAPIKey_Multiple(t *testing.T) {
	// 支持逗号分隔的多个 key
	assert.True(t, validateSyncAPIKey("key1", "key1,key2,key3"))
	assert.True(t, validateSyncAPIKey("key2", "key1,key2,key3"))
	assert.True(t, validateSyncAPIKey("key3", "key1,key2,key3"))
	assert.False(t, validateSyncAPIKey("key4", "key1,key2,key3"))
}

func TestValidateSyncAPIKey_TrimSpace(t *testing.T) {
	// 去除前后空格
	assert.True(t, validateSyncAPIKey("test-key", " test-key "))
	assert.True(t, validateSyncAPIKey("test-key", " test-key"))
	assert.True(t, validateSyncAPIKey("test-key", "test-key "))
}
