package serviceactor

import (
	"fmt"
	"strings"
)

const (
	// AppRuntimeDeliveryPolicyExternal routes App deliveries to a configured
	// callback or runner-stream runtime.
	AppRuntimeDeliveryPolicyExternal = "app_runtime_delivery"
	// AppRuntimeDeliveryPolicyInternalHandler routes App deliveries to a
	// AgentTeam-owned, in-process handler registered by the server composition root.
	AppRuntimeDeliveryPolicyInternalHandler = "app_internal_handler"

	// AppRuntimeConnectionRefExternal is the durable connection route used by
	// callback and runner-stream deliveries.
	AppRuntimeConnectionRefExternal = "app_runtime"
	// AppRuntimeConnectionRefInternalPrefix namespaces process-local handler
	// keys without exposing internal-handler transport through App manifests.
	AppRuntimeConnectionRefInternalPrefix = "builtin:"
)

// InternalHandlerConnectionRef returns the durable service connection ref for
// one AgentTeam-owned handler key.
func InternalHandlerConnectionRef(handlerKey string) (string, error) {
	key := strings.TrimSpace(handlerKey)
	if !validInternalHandlerKey(key) {
		return "", fmt.Errorf("internal handler key is invalid")
	}
	return AppRuntimeConnectionRefInternalPrefix + key, nil
}

// InternalHandlerKeyFromConnectionRef extracts and validates a AgentTeam-owned
// handler key from its durable service connection ref.
func InternalHandlerKeyFromConnectionRef(connectionRef string) (string, bool) {
	ref := strings.TrimSpace(connectionRef)
	if !strings.HasPrefix(ref, AppRuntimeConnectionRefInternalPrefix) {
		return "", false
	}
	key := strings.TrimPrefix(ref, AppRuntimeConnectionRefInternalPrefix)
	if !validInternalHandlerKey(key) {
		return "", false
	}
	return key, true
}

func validInternalHandlerKey(key string) bool {
	if key == "" || len(key) > 128 {
		return false
	}
	for _, char := range key {
		switch {
		case char >= 'a' && char <= 'z':
		case char >= 'A' && char <= 'Z':
		case char >= '0' && char <= '9':
		case char == '.', char == '_', char == '-':
		default:
			return false
		}
	}
	return true
}

func normalizeDeliveryDispatchRoute(transportKind string, deliveryPolicy string, connectionRef string) (string, string, error) {
	policy := trim(deliveryPolicy)
	ref := trim(connectionRef)
	switch trim(transportKind) {
	case RuntimeTransportKindCallback, RuntimeTransportKindRunnerStream:
		if policy == "" {
			policy = AppRuntimeDeliveryPolicyExternal
		}
		if ref == "" {
			ref = AppRuntimeConnectionRefExternal
		}
		if policy != AppRuntimeDeliveryPolicyExternal || ref != AppRuntimeConnectionRefExternal {
			return "", "", badRequest("external App runtime delivery route is invalid")
		}
	case RuntimeTransportKindInternalHandler:
		if policy != AppRuntimeDeliveryPolicyInternalHandler {
			return "", "", badRequest("internal handler delivery policy is invalid")
		}
		if _, ok := InternalHandlerKeyFromConnectionRef(ref); !ok {
			return "", "", badRequest("internal handler connection ref is invalid")
		}
	default:
		return "", "", badRequest("delivery claim transport is invalid")
	}
	return policy, ref, nil
}
