package enidpsync

import (
	"context"
	"net/http"

	"github.com/golang-jwt/jwt/v4"

	"github.com/coder/coder/v2/coderd/idpsync"
	"github.com/coder/coder/v2/codersdk"
)

func (e EnterpriseIDPSync) GroupSyncEnabled() bool {
	return e.entitlements.Enabled(codersdk.FeatureTemplateRBAC)
}

// ParseGroupClaims parses the user claims and handles deployment wide group behavior.
// Almost all behavior is deferred since each organization configures it's own
// group sync settings.
// GroupAllowList is implemented here to prevent login by unauthorized users.
// TODO: GroupAllowList overlaps with the default organization group sync settings.
func (e EnterpriseIDPSync) ParseGroupClaims(ctx context.Context, mergedClaims jwt.MapClaims) (idpsync.GroupParams, *idpsync.HTTPError) {
	if !e.GroupSyncEnabled() {
		return e.AGPLIDPSync.ParseGroupClaims(ctx, mergedClaims)
	}

	if e.GroupField != "" && len(e.GroupAllowList) > 0 {
		groupsRaw, ok := mergedClaims[e.GroupField]
		if !ok {
			return idpsync.GroupParams{}, &idpsync.HTTPError{
				Code:             http.StatusForbidden,
				Msg:              "Not a member of an allowed group",
				Detail:           "You have no groups in your claims!",
				RenderStaticPage: true,
			}
		}
		parsedGroups, err := idpsync.ParseStringSliceClaim(groupsRaw)
		if err != nil {
			return idpsync.GroupParams{}, &idpsync.HTTPError{
				Code:             http.StatusBadRequest,
				Msg:              "Failed read groups from claims for allow list check. Ask an administrator for help.",
				Detail:           err.Error(),
				RenderStaticPage: true,
			}
		}

		inAllowList := false
	AllowListCheckLoop:
		for _, group := range parsedGroups {
			if _, ok := e.GroupAllowList[group]; ok {
				inAllowList = true
				break AllowListCheckLoop
			}
		}

		if !inAllowList {
			return idpsync.GroupParams{}, &idpsync.HTTPError{
				Code:             http.StatusForbidden,
				Msg:              "Not a member of an allowed group",
				Detail:           "Ask an administrator to add one of your groups to the allow list.",
				RenderStaticPage: true,
			}
		}
	}

	return idpsync.GroupParams{
		SyncEnabled:  true,
		MergedClaims: mergedClaims,
	}, nil
}
