// Package grpcsp implements grpc server interceptors to apply role-based
// access control to a grpc service. It is intended to work with headers
// set by [go.skia.org/infra/kube/go/authproxy] on incoming requests.
package grpcsp

import (
	"context"
	"fmt"
	"strings"

	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"

	"go.skia.org/infra/go/roles"
	"go.skia.org/infra/kube/go/authproxy"
)

// ServerPolicy captures the set of authorization policies for
// a given [grpc.Server] instance, including all individual services
// registered to it.
type ServerPolicy struct {
	// maps ServiceName to authorization policy
	servicePolicy map[string]*ServicePolicy
}

// ServicePolicy captures the authorization policy for an individual
// grpc service.
type ServicePolicy struct {
	desc                 grpc.ServiceDesc
	allowUnauthenticated bool
	allowRoles           roles.Roles
	rolesForMethod       map[string]roles.Roles
}

// Server returns a new ServerPolicy instance.
func Server() *ServerPolicy {
	ret := &ServerPolicy{
		servicePolicy: map[string]*ServicePolicy{},
	}
	return ret
}

// Service returns a new configurable ServicePolicy.
// The policy is conservative in that anything that isn't explicitly allowed
// by the policy is denied. Calling this more than once with the same
// [grpc.ServiceDesc] results in an error.
func (sp *ServerPolicy) Service(desc grpc.ServiceDesc) (*ServicePolicy, error) {
	if _, ok := sp.servicePolicy[desc.ServiceName]; ok {
		return nil, fmt.Errorf("service policy already exists for %q", desc.ServiceName)
	}
	ret := &ServicePolicy{
		desc:           desc,
		allowRoles:     nil,
		rolesForMethod: map[string]roles.Roles{},
	}
	for _, m := range desc.Methods {
		fullPath := "/" + desc.ServiceName + "/" + m.MethodName
		ret.rolesForMethod[fullPath] = nil
	}
	sp.servicePolicy[desc.ServiceName] = ret
	return ret, nil
}

// AuthorizeUnauthenticated configures the service to allow any request, regardless
// of authentication or roles attached to the request.
func (p *ServicePolicy) AuthorizeUnauthenticated() error {
	if p.allowRoles != nil {
		return fmt.Errorf("allowed roles for %q have already been set", p.desc.ServiceName)
	}
	p.allowUnauthenticated = true
	return nil
}

// AuthorizeRoles configures the policy to allow users with any of the given [role]
// values to make calls to any method. Authorize multiple roles by passing multiple role
// values. Calling this more than once results in an error.
func (p *ServicePolicy) AuthorizeRoles(r roles.Roles) error {
	if p.allowRoles != nil || p.allowUnauthenticated {
		return fmt.Errorf("allowed roles for %q have already been set", p.desc.ServiceName)
	}
	p.allowRoles = r
	return nil
}

// AuthorizeMethodForRoles configures the policy to allow users with any of the given [role]
// values to make calls to [method]. Authorize multiple roles by passing multiple role
// values. Calling this more than once with the same [method] results in an error. Calling
// this with a method not included in the service description results in an error.
func (p *ServicePolicy) AuthorizeMethodForRoles(method string, r roles.Roles) error {
	if p.allowUnauthenticated {
		return fmt.Errorf("allowed roles for %q have already been set to allow any", p.desc.ServiceName)
	}

	fullPath := "/" + p.desc.ServiceName + "/" + method
	rfm, ok := p.rolesForMethod[fullPath]
	if !ok {
		return fmt.Errorf("unknown grpc method: %q for service %q", method, p.desc.ServiceName)
	}
	if rfm != nil {
		return fmt.Errorf("already have roles set for method: %q", method)
	}

	p.rolesForMethod[fullPath] = r
	return nil
}

// rolesFromContext is dependent on specific headers set by skia's auth-proxy implementation.
func rolesFromContext(ctx context.Context) (roles.Roles, error) {
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return nil, status.Error(codes.PermissionDenied, "could not authorize without metadata from incoming context")
	}
	user := md.Get(authproxy.WebAuthHeaderName)
	if len(user) == 0 {
		return nil, status.Error(codes.PermissionDenied, "could not authorize without user identity from incoming context")
	}
	return roles.RolesFromStrings(md.Get(authproxy.WebAuthRoleHeaderName)...), nil
}

// UnaryInterceptor returns a [grpc.UnaryServerInterceptor] that applies role checks defined
// by the policy to incoming requests. Requests that do not satisfy the policy result in
// a [codes.PermissionDenied] response code returned to the caller.
func (sp *ServerPolicy) UnaryInterceptor() grpc.UnaryServerInterceptor {
	ret := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
		serviceName := strings.Split(info.FullMethod, "/")[1]
		p, ok := sp.servicePolicy[serviceName]
		if !ok {
			return nil, status.Errorf(codes.PermissionDenied, "no policy for service: %q", serviceName)
		}
		if p.allowUnauthenticated {
			return handler(ctx, req)
		}
		roleSet, err := rolesFromContext(ctx)
		if err != nil {
			return nil, status.Error(codes.PermissionDenied, err.Error())
		}
		if p.allowRoles.IsAuthorized(roleSet) {
			return handler(ctx, req)
		}

		allowedRoleSet, ok := p.rolesForMethod[info.FullMethod]
		if !ok {
			return nil, status.Error(codes.PermissionDenied, "unrecognized method")
		}
		if !allowedRoleSet.IsAuthorized(roleSet) {
			return nil, status.Error(codes.PermissionDenied, "user does not have required role(s)")
		}
		return handler(ctx, req)
	}
	return ret
}
