package middleware

import (
	"context"
	"net/http"

	"github.com/gin-gonic/gin"

	"github.com/sundynix/sundynix-gateway/internal/store"
)

// CtxSpaceID 是当前活跃工作区(Space) id 在 gin.Context 的键（增量3 共享工作区）。
const CtxSpaceID = "space_id"

// SpaceContext 解析当前用户在活跃租户内的活跃工作区并注入 space_id。
// 须挂在 Auth + TenantContext 之后（依赖 uid 与 tenant_id）；未登录/无租户则跳过。
// 活跃空间无效（跨租户/已归档/非成员）时由 ActiveSpaceForUser 兜底回退个人空间。
func SpaceContext(db *store.Postgres) gin.HandlerFunc {
	return func(c *gin.Context) {
		uid, _ := c.Get(CtxUserID)
		id, _ := uid.(string)
		tid, _ := c.Get(CtxTenantID)
		tenant, _ := tid.(string)
		if id != "" && tenant != "" {
			if s, err := db.ActiveSpaceForUser(c.Request.Context(), tenant, id); err == nil && s != nil {
				c.Set(CtxSpaceID, s.ID)
			}
		}
		c.Next()
	}
}

// SpaceRoleResolver 解析用户在某空间的角色（*store.Postgres 天然满足）。抽接口便于单测门控。
type SpaceRoleResolver interface {
	SpaceMemberRole(ctx context.Context, spaceID, userID string) string
}

// RequireSpaceRole 要求当前用户在活跃空间中的角色不低于 minRole（按 store.RoleRank 阶梯）。
// 须挂在 RequireAuth + SpaceContext 之后。非成员/无空间 → rank 0 → 拦下。
// 用于共享工作区的写操作门控（建/存/删编排要 ≥member；viewer 只读）。
func RequireSpaceRole(db SpaceRoleResolver, minRole string) gin.HandlerFunc {
	min := store.RoleRank(minRole)
	return func(c *gin.Context) {
		uid, _ := c.Get(CtxUserID)
		id, _ := uid.(string)
		if id == "" {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "需要登录"})
			return
		}
		sid, _ := c.Get(CtxSpaceID)
		space, _ := sid.(string)
		if store.RoleRank(db.SpaceMemberRole(c.Request.Context(), space, id)) < min {
			c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "当前空间角色为只读，无权执行该操作"})
			return
		}
		c.Next()
	}
}
