package api

import (
	"crypto/subtle"
	"net/http"
	"strings"

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

const (
	// HeaderInternalAdminToken carries the service credential for internal admin APIs.
	HeaderInternalAdminToken = "X-AgentTeam-Internal-Admin-Token"

	ctxKeyInternalAdminRequest = "api.internal_admin.request"
)

// InternalAdminRequest captures shared internal-admin request metadata.
type InternalAdminRequest struct {
	Operator string
}

// RequireInternalAdminCredential verifies the service credential and records
// operator metadata for downstream audit fields.
func RequireInternalAdminCredential(configuredToken string) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		expected := strings.TrimSpace(configuredToken)
		if expected == "" {
			Error(ctx, http.StatusServiceUnavailable, "Internal admin credential is not configured")
			ctx.Abort()
			return
		}
		presented := strings.TrimSpace(ctx.GetHeader(HeaderInternalAdminToken))
		if presented == "" {
			if bearer, ok := BearerToken(ctx); ok {
				presented = bearer
			}
		}
		if presented == "" || subtle.ConstantTimeCompare([]byte(presented), []byte(expected)) != 1 {
			Error(ctx, http.StatusUnauthorized, "Invalid internal admin credential")
			ctx.Abort()
			return
		}
		ctx.Set(ctxKeyInternalAdminRequest, InternalAdminRequest{Operator: internalAdminOperatorFromHeaders(ctx)})
		ctx.Next()
	}
}

// InternalAdminOperator returns the forwarded agentteam-ops operator identity.
func InternalAdminOperator(ctx *gin.Context) string {
	if ctx == nil {
		return "unknown"
	}
	if value, ok := ctx.Get(ctxKeyInternalAdminRequest); ok {
		if request, ok := value.(InternalAdminRequest); ok {
			if operator := strings.TrimSpace(request.Operator); operator != "" {
				return operator
			}
		}
	}
	return internalAdminOperatorFromHeaders(ctx)
}

func internalAdminOperatorFromHeaders(ctx *gin.Context) string {
	for _, header := range []string{
		"X-AgentTeam-Ops-Operator-Id",
		"X-AgentTeam-Ops-Operator-Email",
		"X-AgentTeam-Ops-Operator-Name",
	} {
		if value := strings.TrimSpace(ctx.GetHeader(header)); value != "" {
			return value
		}
	}
	return "unknown"
}
