package permissionsimp

import (
	"net/http"

	"github.com/tech/sendico/pkg/api/http/response"
	"github.com/tech/sendico/pkg/model"
	"github.com/tech/sendico/pkg/mutil/mzap"
	"github.com/tech/sendico/server/interface/api/sresponse"
	mutil "github.com/tech/sendico/server/internal/mutil/param"
	"go.uber.org/zap"
)

func (a *PermissionsAPI) get(r *http.Request, account *model.Account, accessToken *sresponse.TokenData) http.HandlerFunc {
	orgRef, err := mutil.GetOrganizationRef(r)
	if err != nil {
		a.logger.Warn("Failed to restore organization reference", zap.Error(err), zap.String("organization_ref", mutil.GetOrganizationID(r)))
		return response.BadReference(a.logger, a.Name(), mutil.OrganizationRefName(), mutil.GetOrganizationID(r), err)
	}
	ctx := r.Context()
	roles, permissions, err := a.enforcer.GetPermissions(ctx, *account.GetID(), orgRef)
	if len(roles) == 0 {
		a.logger.Warn("No roles defined for account", mzap.StorableRef(account), mzap.ObjRef("organization_ref", orgRef))
		return response.AccessDenied(a.logger, a.Name(), "User has no roles assigned")
	}
	if err != nil {
		a.logger.Warn("Failed to fetch account policies", zap.Error(err), mzap.ObjRef("organization_ref", orgRef))
		return response.Internal(a.logger, a.Name(), err)
	}
	roleDescs, err := a.rdb.List(ctx, orgRef, nil)
	if err != nil {
		a.logger.Warn("Failed to fetch organization roles", mzap.ObjRef("organization_ref", orgRef))
		return response.Internal(a.logger, a.Name(), err)
	}
	policies, err := a.getRolePolicies(ctx, roleDescs)
	if err != nil {
		a.logger.Warn("Failed to fetch roles policies", zap.Error(err))
		return response.Auto(a.logger, a.Name(), err)
	}
	permDescs, err := a.pdb.All(ctx, orgRef)
	if err != nil {
		a.logger.Warn("Failed to fetch organization permissions", mzap.ObjRef("organization_ref", orgRef))
		return response.Internal(a.logger, a.Name(), err)
	}

	return sresponse.Permisssions(a.logger,
		roleDescs, permDescs,
		roles, policies, permissions,
		accessToken,
	)
}
