package middleware

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"

	"hfb_sys/backend/pkg/response"

	"github.com/gin-gonic/gin"
	"github.com/redis/go-redis/v9"
)

// RequirePermission 检查当前管理员是否拥有指定权限。
// 超级管理员（拥有 super_admin 角色的管理员）自动放行。
func RequirePermission(permCode string, rdb *redis.Client) gin.HandlerFunc {
	return func(c *gin.Context) {
		value, ok := c.Get(ContextAdminID)
		if !ok {
			response.Unauthorized(c, "缺少管理员上下文")
			c.Abort()
			return
		}
		adminID, ok := value.(uint64)
		if !ok {
			response.Unauthorized(c, "管理员上下文无效")
			c.Abort()
			return
		}

		codes, err := getPermCodes(c, rdb, adminID)
		if err != nil {
			response.Error(c, http.StatusInternalServerError, "perm_check_failed", "权限校验服务暂时不可用")
			c.Abort()
			return
		}

		for _, code := range codes {
			if code == permCode || code == "*" {
				c.Next()
				return
			}
		}

		response.Error(c, http.StatusForbidden, "forbidden", "没有操作权限")
		c.Abort()
	}
}

func getPermCodes(c *gin.Context, rdb *redis.Client, adminID uint64) ([]string, error) {
	if rdb == nil {
		return nil, errors.New("redis unavailable")
	}
	ctx := context.Background()
	key := fmt.Sprintf("admin:perms:%d", adminID)
	raw, err := rdb.Get(ctx, key).Result()
	if errors.Is(err, redis.Nil) {
		return nil, nil // 缓存未命中，视为无权限
	}
	if err != nil {
		return nil, err
	}
	var codes []string
	if err := json.Unmarshal([]byte(raw), &codes); err != nil {
		return nil, err
	}
	return codes, nil
}
