package middleware

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

	"github.com/gin-gonic/gin"
)

func init() {
	gin.SetMode(gin.TestMode)
}

// stubAuth 记录是否被调用, abort=true 时调用 c.Abort()
type stubAuth struct {
	called bool
	abort  bool
}

func (s *stubAuth) handler() gin.HandlerFunc {
	return func(c *gin.Context) {
		s.called = true
		if s.abort {
			c.Abort()
		}
	}
}

func runCombinedAuth(agent, jwt gin.HandlerFunc, headers map[string]string) {
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	req := httptest.NewRequest(http.MethodGet, "/", nil)
	for k, v := range headers {
		req.Header.Set(k, v)
	}
	c.Request = req
	CombinedAuth(agent, jwt)(c)
}

func TestCombinedAuth(t *testing.T) {
	t.Run("无 X-API-Key 只走 jwtAuth", func(t *testing.T) {
		agent, jwtStub := &stubAuth{}, &stubAuth{}
		runCombinedAuth(agent.handler(), jwtStub.handler(), map[string]string{
			"Authorization": "Bearer token",
		})
		if agent.called {
			t.Error("agentAuth 不应被调用")
		}
		if !jwtStub.called {
			t.Error("jwtAuth 应被调用")
		}
	})

	t.Run("有 X-API-Key 只走 agentAuth", func(t *testing.T) {
		agent, jwtStub := &stubAuth{}, &stubAuth{}
		runCombinedAuth(agent.handler(), jwtStub.handler(), map[string]string{
			"X-API-Key": "some-key",
		})
		if !agent.called {
			t.Error("agentAuth 应被调用")
		}
		if jwtStub.called {
			t.Error("jwtAuth 不应被调用")
		}
	})

	t.Run("同时有 X-API-Key 和 Authorization 仍只走 agentAuth", func(t *testing.T) {
		agent, jwtStub := &stubAuth{}, &stubAuth{}
		runCombinedAuth(agent.handler(), jwtStub.handler(), map[string]string{
			"X-API-Key":     "some-key",
			"Authorization": "Bearer token",
		})
		if !agent.called {
			t.Error("agentAuth 应被调用")
		}
		if jwtStub.called {
			t.Error("jwtAuth 不应被调用")
		}
	})

	t.Run("agentAuth abort 后不得再调 jwtAuth", func(t *testing.T) {
		agent, jwtStub := &stubAuth{abort: true}, &stubAuth{}
		runCombinedAuth(agent.handler(), jwtStub.handler(), map[string]string{
			"X-API-Key": "bad-key",
		})
		if !agent.called {
			t.Error("agentAuth 应被调用")
		}
		if jwtStub.called {
			t.Error("agentAuth abort 后 jwtAuth 不应被调用")
		}
	})

	t.Run("X-API-Key 为纯空格视为无 key 走 jwtAuth", func(t *testing.T) {
		agent, jwtStub := &stubAuth{}, &stubAuth{}
		w := httptest.NewRecorder()
		c, _ := gin.CreateTestContext(w)
		req := httptest.NewRequest(http.MethodGet, "/", nil)
		req.Header["X-Api-Key"] = []string{"   "} // 直接设置, 绕过 Header.Set 的 trim
		c.Request = req
		CombinedAuth(agent.handler(), jwtStub.handler())(c)
		if agent.called {
			t.Error("纯空格 X-API-Key 不应走 agentAuth")
		}
		if !jwtStub.called {
			t.Error("纯空格 X-API-Key 应走 jwtAuth")
		}
	})
}
