package middleware

import (
	"net/http"

	"github.com/ultisuite/ulti-backend/internal/api/apiresponse"
	"github.com/ultisuite/ulti-backend/internal/permission"
)

func RequireRole(roles ...permission.Role) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			claims := ClaimsFromContext(r.Context())
			if claims == nil {
				apiresponse.WriteError(w, r, http.StatusUnauthorized, apiresponse.CodeAuthUnauthorized, "unauthorized", nil)
				return
			}
			if !permission.HasAnyRole(claims.Groups, roles...) {
				apiresponse.WriteError(w, r, http.StatusForbidden, apiresponse.CodeAuthForbidden, "forbidden", nil)
				return
			}
			next.ServeHTTP(w, r)
		})
	}
}

func RequirePermission(resource permission.Resource, level permission.Level) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if ApiTokenFromContext(r.Context()) != nil {
				next.ServeHTTP(w, r)
				return
			}
			claims := ClaimsFromContext(r.Context())
			if claims == nil {
				apiresponse.WriteError(w, r, http.StatusUnauthorized, apiresponse.CodeAuthUnauthorized, "unauthorized", nil)
				return
			}
			if !permission.HasPermission(claims.Groups, resource, level) {
				apiresponse.WriteError(w, r, http.StatusForbidden, apiresponse.CodeAuthForbidden, "forbidden", nil)
				return
			}
			next.ServeHTTP(w, r)
		})
	}
}

// RequireFullAccount blocks guest (invited) accounts from full-suite modules.
func RequireFullAccount(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if ApiTokenFromContext(r.Context()) != nil {
			next.ServeHTTP(w, r)
			return
		}
		claims := ClaimsFromContext(r.Context())
		if claims == nil {
			apiresponse.WriteError(w, r, http.StatusUnauthorized, apiresponse.CodeAuthUnauthorized, "unauthorized", nil)
			return
		}
		if permission.HasRole(claims.Groups, permission.RoleGuest) {
			apiresponse.WriteError(w, r, http.StatusForbidden, apiresponse.CodeAuthForbidden, "guest accounts may only access shared drive content", nil)
			return
		}
		next.ServeHTTP(w, r)
	})
}

func RequireAdminScope(scope permission.AdminScope) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			claims := ClaimsFromContext(r.Context())
			if claims == nil {
				apiresponse.WriteError(w, r, http.StatusUnauthorized, apiresponse.CodeAuthUnauthorized, "unauthorized", nil)
				return
			}
			if !permission.HasRole(claims.Groups, permission.RoleAdmin) {
				apiresponse.WriteError(w, r, http.StatusForbidden, apiresponse.CodeAuthForbidden, "forbidden", nil)
				return
			}
			if !permission.HasAdminScope(claims.Groups, scope) {
				apiresponse.WriteError(w, r, http.StatusForbidden, apiresponse.CodeAuthForbidden, "forbidden", nil)
				return
			}
			next.ServeHTTP(w, r)
		})
	}
}
