// This file is auto-generated by alef — DO NOT EDIT.
// alef:hash:4e15143f4af1ae8bafbdb1506ef057da924484c66a19483966333558ad437e75
// To regenerate: alef generate
// To verify freshness: alef verify --exit-code
// Issues & docs: https://github.com/kreuzberg-dev/alef
package kreuzberg

/*
#cgo CFLAGS: -I${SRCDIR}/include
#include "kreuzberg.h"
#include <stdlib.h>
#include <string.h>

extern int32_t goOcrBackendProcessImage(void* user_data, uint8_t* image_bytes, size_t image_bytes_len, char* config, char** out_result, char** out_error);
extern int32_t goOcrBackendProcessImageFile(void* user_data, char* path, char* config, char** out_result, char** out_error);
extern int32_t goOcrBackendSupportsLanguage(void* user_data, char* lang, char** out_result, char** out_error);
extern int32_t goOcrBackendBackendType(void* user_data, char** out_result, char** out_error);
extern int32_t goOcrBackendSupportedLanguages(void* user_data, char** out_result, char** out_error);
extern int32_t goOcrBackendSupportsTableDetection(void* user_data, char** out_result, char** out_error);
extern int32_t goOcrBackendSupportsDocumentProcessing(void* user_data, char** out_result, char** out_error);
extern int32_t goOcrBackendProcessDocument(void* user_data, char* _path, char* _config, char** out_result, char** out_error);
extern int32_t goOcrBackendName(void*, char**, char**);
extern int32_t goOcrBackendVersion(void*, char**, char**);
extern int32_t goOcrBackendInitialize(void*, char**);
extern int32_t goOcrBackendShutdown(void*, char**);
extern void goOcrBackendFreeUserData(void*);
extern void goOcrBackendFreeString(char*);
extern int32_t goPostProcessorProcess(void* user_data, char* result, char* config, char** out_error);
extern int32_t goPostProcessorProcessingStage(void* user_data, char** out_result, char** out_error);
extern int32_t goPostProcessorShouldProcess(void* user_data, char* _result, char* _config, char** out_result, char** out_error);
extern int32_t goPostProcessorEstimatedDurationMs(void* user_data, char* _result, char** out_result, char** out_error);
extern int32_t goPostProcessorPriority(void* user_data, char** out_result, char** out_error);
extern int32_t goPostProcessorName(void*, char**, char**);
extern int32_t goPostProcessorVersion(void*, char**, char**);
extern int32_t goPostProcessorInitialize(void*, char**);
extern int32_t goPostProcessorShutdown(void*, char**);
extern void goPostProcessorFreeUserData(void*);
extern void goPostProcessorFreeString(char*);
extern int32_t goValidatorValidate(void* user_data, char* result, char* config, char** out_error);
extern int32_t goValidatorShouldValidate(void* user_data, char* _result, char* _config, char** out_result, char** out_error);
extern int32_t goValidatorPriority(void* user_data, char** out_result, char** out_error);
extern int32_t goValidatorName(void*, char**, char**);
extern int32_t goValidatorVersion(void*, char**, char**);
extern int32_t goValidatorInitialize(void*, char**);
extern int32_t goValidatorShutdown(void*, char**);
extern void goValidatorFreeUserData(void*);
extern void goValidatorFreeString(char*);
extern int32_t goEmbeddingBackendDimensions(void* user_data, char** out_result, char** out_error);
extern int32_t goEmbeddingBackendEmbed(void* user_data, char* texts, char** out_result, char** out_error);
extern int32_t goEmbeddingBackendName(void*, char**, char**);
extern int32_t goEmbeddingBackendVersion(void*, char**, char**);
extern int32_t goEmbeddingBackendInitialize(void*, char**);
extern int32_t goEmbeddingBackendShutdown(void*, char**);
extern void goEmbeddingBackendFreeUserData(void*);
extern void goEmbeddingBackendFreeString(char*);
extern int32_t goDocumentExtractorExtractBytes(void* user_data, uint8_t* content, size_t content_len, char* mime_type, char* config, char** out_result, char** out_error);
extern int32_t goDocumentExtractorExtractFile(void* user_data, char* path, char* mime_type, char* config, char** out_result, char** out_error);
extern int32_t goDocumentExtractorSupportedMimeTypes(void* user_data, char** out_result, char** out_error);
extern int32_t goDocumentExtractorPriority(void* user_data, char** out_result, char** out_error);
extern int32_t goDocumentExtractorCanHandle(void* user_data, char* _path, char* _mime_type, char** out_result, char** out_error);
extern int32_t goDocumentExtractorName(void*, char**, char**);
extern int32_t goDocumentExtractorVersion(void*, char**, char**);
extern int32_t goDocumentExtractorInitialize(void*, char**);
extern int32_t goDocumentExtractorShutdown(void*, char**);
extern void goDocumentExtractorFreeUserData(void*);
extern void goDocumentExtractorFreeString(char*);
extern int32_t goRendererRender(void* user_data, char* doc, char** out_result, char** out_error);
extern int32_t goRendererName(void*, char**, char**);
extern int32_t goRendererVersion(void*, char**, char**);
extern int32_t goRendererInitialize(void*, char**);
extern int32_t goRendererShutdown(void*, char**);
extern void goRendererFreeUserData(void*);
extern void goRendererFreeString(char*);
*/
import "C"

import (
	"encoding/json"
	"fmt"
	"runtime/cgo"
	"sync"
	"unsafe"
)

// handleRegistry tracks cgo.Handles by name to ensure proper cleanup on unregister.
// Without this, unregistered plugins can cause use-after-free crashes when Rust
// still holds vtable pointers and tries to invoke callbacks on deleted handles.
type handleRegistry struct {
	mu      sync.Mutex
	handles map[string]cgo.Handle
}

var (
	ocr_backendRegistry = &handleRegistry{handles: make(map[string]cgo.Handle)}
	post_processorRegistry = &handleRegistry{handles: make(map[string]cgo.Handle)}
	validatorRegistry = &handleRegistry{handles: make(map[string]cgo.Handle)}
	embedding_backendRegistry = &handleRegistry{handles: make(map[string]cgo.Handle)}
	document_extractorRegistry = &handleRegistry{handles: make(map[string]cgo.Handle)}
	rendererRegistry = &handleRegistry{handles: make(map[string]cgo.Handle)}
)

// store adds a handle to the registry, keyed by name.
func (reg *handleRegistry) store(name string, handle cgo.Handle) {
	reg.mu.Lock()
	defer reg.mu.Unlock()
	if old, ok := reg.handles[name]; ok {
		old.Delete()
	}
	reg.handles[name] = handle
}

// delete removes and deletes a handle from the registry by name.
func (reg *handleRegistry) delete(name string) {
	reg.mu.Lock()
	defer reg.mu.Unlock()
	if handle, ok := reg.handles[name]; ok {
		delete(reg.handles, name)
		handle.Delete()
	}
}

// clear removes and deletes all handles from the registry.
func (reg *handleRegistry) clear() {
	reg.mu.Lock()
	defer reg.mu.Unlock()
	for _, handle := range reg.handles {
		handle.Delete()
	}
	reg.handles = make(map[string]cgo.Handle)
}

// OcrBackend defines the Go interface for the OcrBackend trait.
type OcrBackend interface {
	// Name returns the plugin name.
	Name() string
	// Version returns the plugin version.
	Version() string
	// Initialize is called when the plugin is loaded.
	Initialize() error
	// Shutdown is called when the plugin is unloaded.
	Shutdown() error
	// process_image
	ProcessImage(image_bytes []byte, config OcrConfig) (ExtractionResult, error)

	// process_image_file
	ProcessImageFile(path string, config OcrConfig) (ExtractionResult, error)

	// supports_language
	SupportsLanguage(lang string) bool

	// backend_type
	BackendType() OcrBackendType

	// supported_languages
	SupportedLanguages() []string

	// supports_table_detection
	SupportsTableDetection() bool

	// supports_document_processing
	SupportsDocumentProcessing() bool

	// process_document
	ProcessDocument(_path string, _config OcrConfig) (ExtractionResult, error)

}

//export goOcrBackendProcessImage
func goOcrBackendProcessImage(
	userData unsafe.Pointer,
	image_bytes *C.uint8_t,
	image_bytesLen C.size_t,
	config *C.char,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(OcrBackend)

	if !ok {
		return 1  // error: invalid handle
	}

	var goImage_bytes []byte
	if image_bytes != nil {
		goImage_bytes = unsafe.Slice((*byte)(unsafe.Pointer(image_bytes)), int(image_bytesLen))
	}

		var goConfig OcrConfig
		if config != nil {
			json.Unmarshal([]byte(C.GoString(config)), &goConfig)

	}

	// Call the method
		result, err := impl.ProcessImage(goImage_bytes, goConfig)

	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goOcrBackendProcessImageFile
func goOcrBackendProcessImageFile(
	userData unsafe.Pointer,
	path *C.char,
	config *C.char,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(OcrBackend)

	if !ok {
		return 1  // error: invalid handle
	}

		goPath := C.GoString(path)

		var goConfig OcrConfig
		if config != nil {
			json.Unmarshal([]byte(C.GoString(config)), &goConfig)

	}

	// Call the method
		result, err := impl.ProcessImageFile(goPath, goConfig)

	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goOcrBackendSupportsLanguage
func goOcrBackendSupportsLanguage(
	userData unsafe.Pointer,
	lang *C.char,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(OcrBackend)

	if !ok {
		return 1  // error: invalid handle
	}

		goLang := C.GoString(lang)

	// Call the method
		result := impl.SupportsLanguage(goLang)

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goOcrBackendBackendType
func goOcrBackendBackendType(
	userData unsafe.Pointer,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(OcrBackend)

	if !ok {
		return 1  // error: invalid handle
	}

	// Call the method
		result := impl.BackendType()

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goOcrBackendSupportedLanguages
func goOcrBackendSupportedLanguages(
	userData unsafe.Pointer,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(OcrBackend)

	if !ok {
		return 1  // error: invalid handle
	}

	// Call the method
		result := impl.SupportedLanguages()

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goOcrBackendSupportsTableDetection
func goOcrBackendSupportsTableDetection(
	userData unsafe.Pointer,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(OcrBackend)

	if !ok {
		return 1  // error: invalid handle
	}

	// Call the method
		result := impl.SupportsTableDetection()

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goOcrBackendSupportsDocumentProcessing
func goOcrBackendSupportsDocumentProcessing(
	userData unsafe.Pointer,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(OcrBackend)

	if !ok {
		return 1  // error: invalid handle
	}

	// Call the method
		result := impl.SupportsDocumentProcessing()

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goOcrBackendProcessDocument
func goOcrBackendProcessDocument(
	userData unsafe.Pointer,
	_path *C.char,
	_config *C.char,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(OcrBackend)

	if !ok {
		return 1  // error: invalid handle
	}

		go_path := C.GoString(_path)

		var go_config OcrConfig
		if _config != nil {
			json.Unmarshal([]byte(C.GoString(_config)), &go_config)

	}

	// Call the method
		result, err := impl.ProcessDocument(go_path, go_config)

	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goOcrBackendName
func goOcrBackendName(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(OcrBackend)

	if !ok {
		return 1
	}
	name := impl.Name()
	cName := C.CString(name)
	*outResult = cName
	return 0
}

//export goOcrBackendVersion
func goOcrBackendVersion(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(OcrBackend)

	if !ok {
		return 1
	}
	version := impl.Version()
	cVersion := C.CString(version)
	*outResult = cVersion
	return 0
}

//export goOcrBackendInitialize
func goOcrBackendInitialize(userData unsafe.Pointer, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(OcrBackend)

	if !ok {
		return 1
	}
	err := impl.Initialize()
	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0
}

//export goOcrBackendShutdown
func goOcrBackendShutdown(userData unsafe.Pointer, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(OcrBackend)

	if !ok {
		return 1
	}
	err := impl.Shutdown()
	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0
}

//export goOcrBackendFreeUserData
func goOcrBackendFreeUserData(userData unsafe.Pointer) {

	// No-op to avoid cleanup-queue panics. Handles cleaned in Unregister().
}

//export goOcrBackendFreeString
func goOcrBackendFreeString(ptr *C.char) {
	if ptr != nil {
		C.free(unsafe.Pointer(ptr))
	}
}

// RegisterOcrBackend registers a OcrBackend implementation with the C runtime.
func RegisterOcrBackend(impl OcrBackend) error {
	handle := cgo.NewHandle(impl)
	// Build the C vtable  DEBUG:c_vtable_struct=KREUZBERGKreuzbergOcrBackendVTable
	vtable := C.KREUZBERGKreuzbergOcrBackendVTable{
		process_image: (*[0]byte)(unsafe.Pointer(C.goOcrBackendProcessImage)),
		process_image_file: (*[0]byte)(unsafe.Pointer(C.goOcrBackendProcessImageFile)),
		supports_language: (*[0]byte)(unsafe.Pointer(C.goOcrBackendSupportsLanguage)),
		backend_type: (*[0]byte)(unsafe.Pointer(C.goOcrBackendBackendType)),
		supported_languages: (*[0]byte)(unsafe.Pointer(C.goOcrBackendSupportedLanguages)),
		supports_table_detection: (*[0]byte)(unsafe.Pointer(C.goOcrBackendSupportsTableDetection)),
		supports_document_processing: (*[0]byte)(unsafe.Pointer(C.goOcrBackendSupportsDocumentProcessing)),
		process_document: (*[0]byte)(unsafe.Pointer(C.goOcrBackendProcessDocument)),
		name_fn: (*[0]byte)(unsafe.Pointer(C.goOcrBackendName)),
		version_fn: (*[0]byte)(unsafe.Pointer(C.goOcrBackendVersion)),
		initialize_fn: (*[0]byte)(unsafe.Pointer(C.goOcrBackendInitialize)),
		shutdown_fn: (*[0]byte)(unsafe.Pointer(C.goOcrBackendShutdown)),
		free_string: (*[0]byte)(unsafe.Pointer(C.goOcrBackendFreeString)),
		free_user_data: (*[0]byte)(unsafe.Pointer(C.goOcrBackendFreeUserData)),
	}

	// Call C registration
	cName := C.CString(impl.Name())
	defer C.free(unsafe.Pointer(cName))

	var cErr *C.char
	rc := C.kreuzberg_register_ocr_backend(
		cName,
		vtable,
		unsafe.Pointer(uintptr(handle)),
		&cErr,
	)

	if rc != 0 {
		msg := "failed to register OcrBackend"
		if cErr != nil {
			msg = C.GoString(cErr)
			C.kreuzberg_free_string(cErr)
		}
		handle.Delete()
		return fmt.Errorf("%s", msg)
	}

	// Store handle by name for later cleanup on unregister
	ocr_backendRegistry.store(impl.Name(), handle)
	return nil
}

// UnregisterOcrBackend unregisters a OcrBackend implementation.
func UnregisterOcrBackend(name string) error {
	cName := C.CString(name)
	defer C.free(unsafe.Pointer(cName))
	var cErr *C.char
	rc := C.kreuzberg_unregister_ocr_backend(cName, &cErr)

	if rc != 0 {
	msg := "failed to unregister OcrBackend"
	if cErr != nil {
		msg = C.GoString(cErr)
		C.kreuzberg_free_string(cErr)
	}
	return fmt.Errorf("%s", msg)
	}

	// Delete the handle now that Rust has unregistered the plugin
	ocr_backendRegistry.delete(name)
	return nil
}

// ClearOcrBackends removes all registered OcrBackend implementations.
func ClearOcrBackends() error {
	var cErr *C.char
	rc := C.kreuzberg_clear_ocr_backend(&cErr)

	if rc != 0 {
		msg := "failed to clear OcrBackend plugins"
		if cErr != nil {
			msg = C.GoString(cErr)
			C.free(unsafe.Pointer(cErr))
		}
		return fmt.Errorf("%s", msg)
	}

	// Delete all handles now that Rust has cleared all plugins
	ocr_backendRegistry.clear()
	return nil
}

// PostProcessor defines the Go interface for the PostProcessor trait.
type PostProcessor interface {
	// Name returns the plugin name.
	Name() string
	// Version returns the plugin version.
	Version() string
	// Initialize is called when the plugin is loaded.
	Initialize() error
	// Shutdown is called when the plugin is unloaded.
	Shutdown() error
	// process
	Process(result ExtractionResult, config ExtractionConfig) error

	// processing_stage
	ProcessingStage() ProcessingStage

	// should_process
	ShouldProcess(_result ExtractionResult, _config ExtractionConfig) bool

	// estimated_duration_ms
	EstimatedDurationMs(_result ExtractionResult) uint64

	// priority
	Priority() int32

}

//export goPostProcessorProcess
func goPostProcessorProcess(
	userData unsafe.Pointer,
	result *C.char,
	config *C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(PostProcessor)

	if !ok {
		return 1  // error: invalid handle
	}

		var goResult ExtractionResult
		if result != nil {
			json.Unmarshal([]byte(C.GoString(result)), &goResult)

	}

		var goConfig ExtractionConfig
		if config != nil {
			json.Unmarshal([]byte(C.GoString(config)), &goConfig)

	}

	// Call the method
		err := impl.Process(goResult, goConfig)

	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0  // success
}

//export goPostProcessorProcessingStage
func goPostProcessorProcessingStage(
	userData unsafe.Pointer,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(PostProcessor)

	if !ok {
		return 1  // error: invalid handle
	}

	// Call the method
		result := impl.ProcessingStage()

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goPostProcessorShouldProcess
func goPostProcessorShouldProcess(
	userData unsafe.Pointer,
	_result *C.char,
	_config *C.char,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(PostProcessor)

	if !ok {
		return 1  // error: invalid handle
	}

		var go_result ExtractionResult
		if _result != nil {
			json.Unmarshal([]byte(C.GoString(_result)), &go_result)

	}

		var go_config ExtractionConfig
		if _config != nil {
			json.Unmarshal([]byte(C.GoString(_config)), &go_config)

	}

	// Call the method
		result := impl.ShouldProcess(go_result, go_config)

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goPostProcessorEstimatedDurationMs
func goPostProcessorEstimatedDurationMs(
	userData unsafe.Pointer,
	_result *C.char,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(PostProcessor)

	if !ok {
		return 1  // error: invalid handle
	}

		var go_result ExtractionResult
		if _result != nil {
			json.Unmarshal([]byte(C.GoString(_result)), &go_result)

	}

	// Call the method
		result := impl.EstimatedDurationMs(go_result)

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goPostProcessorPriority
func goPostProcessorPriority(
	userData unsafe.Pointer,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(PostProcessor)

	if !ok {
		return 1  // error: invalid handle
	}

	// Call the method
		result := impl.Priority()

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goPostProcessorName
func goPostProcessorName(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(PostProcessor)

	if !ok {
		return 1
	}
	name := impl.Name()
	cName := C.CString(name)
	*outResult = cName
	return 0
}

//export goPostProcessorVersion
func goPostProcessorVersion(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(PostProcessor)

	if !ok {
		return 1
	}
	version := impl.Version()
	cVersion := C.CString(version)
	*outResult = cVersion
	return 0
}

//export goPostProcessorInitialize
func goPostProcessorInitialize(userData unsafe.Pointer, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(PostProcessor)

	if !ok {
		return 1
	}
	err := impl.Initialize()
	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0
}

//export goPostProcessorShutdown
func goPostProcessorShutdown(userData unsafe.Pointer, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(PostProcessor)

	if !ok {
		return 1
	}
	err := impl.Shutdown()
	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0
}

//export goPostProcessorFreeUserData
func goPostProcessorFreeUserData(userData unsafe.Pointer) {

	// No-op to avoid cleanup-queue panics. Handles cleaned in Unregister().
}

//export goPostProcessorFreeString
func goPostProcessorFreeString(ptr *C.char) {
	if ptr != nil {
		C.free(unsafe.Pointer(ptr))
	}
}

// RegisterPostProcessor registers a PostProcessor implementation with the C runtime.
func RegisterPostProcessor(impl PostProcessor) error {
	handle := cgo.NewHandle(impl)
	// Build the C vtable  DEBUG:c_vtable_struct=KREUZBERGKreuzbergPostProcessorVTable
	vtable := C.KREUZBERGKreuzbergPostProcessorVTable{
		process: (*[0]byte)(unsafe.Pointer(C.goPostProcessorProcess)),
		processing_stage: (*[0]byte)(unsafe.Pointer(C.goPostProcessorProcessingStage)),
		should_process: (*[0]byte)(unsafe.Pointer(C.goPostProcessorShouldProcess)),
		estimated_duration_ms: (*[0]byte)(unsafe.Pointer(C.goPostProcessorEstimatedDurationMs)),
		priority: (*[0]byte)(unsafe.Pointer(C.goPostProcessorPriority)),
		name_fn: (*[0]byte)(unsafe.Pointer(C.goPostProcessorName)),
		version_fn: (*[0]byte)(unsafe.Pointer(C.goPostProcessorVersion)),
		initialize_fn: (*[0]byte)(unsafe.Pointer(C.goPostProcessorInitialize)),
		shutdown_fn: (*[0]byte)(unsafe.Pointer(C.goPostProcessorShutdown)),
		free_string: (*[0]byte)(unsafe.Pointer(C.goPostProcessorFreeString)),
		free_user_data: (*[0]byte)(unsafe.Pointer(C.goPostProcessorFreeUserData)),
	}

	// Call C registration
	cName := C.CString(impl.Name())
	defer C.free(unsafe.Pointer(cName))

	var cErr *C.char
	rc := C.kreuzberg_register_post_processor(
		cName,
		vtable,
		unsafe.Pointer(uintptr(handle)),
		&cErr,
	)

	if rc != 0 {
		msg := "failed to register PostProcessor"
		if cErr != nil {
			msg = C.GoString(cErr)
			C.kreuzberg_free_string(cErr)
		}
		handle.Delete()
		return fmt.Errorf("%s", msg)
	}

	// Store handle by name for later cleanup on unregister
	post_processorRegistry.store(impl.Name(), handle)
	return nil
}

// UnregisterPostProcessor unregisters a PostProcessor implementation.
func UnregisterPostProcessor(name string) error {
	cName := C.CString(name)
	defer C.free(unsafe.Pointer(cName))
	var cErr *C.char
	rc := C.kreuzberg_unregister_post_processor(cName, &cErr)

	if rc != 0 {
	msg := "failed to unregister PostProcessor"
	if cErr != nil {
		msg = C.GoString(cErr)
		C.kreuzberg_free_string(cErr)
	}
	return fmt.Errorf("%s", msg)
	}

	// Delete the handle now that Rust has unregistered the plugin
	post_processorRegistry.delete(name)
	return nil
}

// ClearPostProcessors removes all registered PostProcessor implementations.
func ClearPostProcessors() error {
	var cErr *C.char
	rc := C.kreuzberg_clear_post_processor(&cErr)

	if rc != 0 {
		msg := "failed to clear PostProcessor plugins"
		if cErr != nil {
			msg = C.GoString(cErr)
			C.free(unsafe.Pointer(cErr))
		}
		return fmt.Errorf("%s", msg)
	}

	// Delete all handles now that Rust has cleared all plugins
	post_processorRegistry.clear()
	return nil
}

// Validator defines the Go interface for the Validator trait.
type Validator interface {
	// Name returns the plugin name.
	Name() string
	// Version returns the plugin version.
	Version() string
	// Initialize is called when the plugin is loaded.
	Initialize() error
	// Shutdown is called when the plugin is unloaded.
	Shutdown() error
	// validate
	Validate(result ExtractionResult, config ExtractionConfig) error

	// should_validate
	ShouldValidate(_result ExtractionResult, _config ExtractionConfig) bool

	// priority
	Priority() int32

}

//export goValidatorValidate
func goValidatorValidate(
	userData unsafe.Pointer,
	result *C.char,
	config *C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(Validator)

	if !ok {
		return 1  // error: invalid handle
	}

		var goResult ExtractionResult
		if result != nil {
			json.Unmarshal([]byte(C.GoString(result)), &goResult)

	}

		var goConfig ExtractionConfig
		if config != nil {
			json.Unmarshal([]byte(C.GoString(config)), &goConfig)

	}

	// Call the method
		err := impl.Validate(goResult, goConfig)

	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0  // success
}

//export goValidatorShouldValidate
func goValidatorShouldValidate(
	userData unsafe.Pointer,
	_result *C.char,
	_config *C.char,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(Validator)

	if !ok {
		return 1  // error: invalid handle
	}

		var go_result ExtractionResult
		if _result != nil {
			json.Unmarshal([]byte(C.GoString(_result)), &go_result)

	}

		var go_config ExtractionConfig
		if _config != nil {
			json.Unmarshal([]byte(C.GoString(_config)), &go_config)

	}

	// Call the method
		result := impl.ShouldValidate(go_result, go_config)

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goValidatorPriority
func goValidatorPriority(
	userData unsafe.Pointer,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(Validator)

	if !ok {
		return 1  // error: invalid handle
	}

	// Call the method
		result := impl.Priority()

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goValidatorName
func goValidatorName(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(Validator)

	if !ok {
		return 1
	}
	name := impl.Name()
	cName := C.CString(name)
	*outResult = cName
	return 0
}

//export goValidatorVersion
func goValidatorVersion(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(Validator)

	if !ok {
		return 1
	}
	version := impl.Version()
	cVersion := C.CString(version)
	*outResult = cVersion
	return 0
}

//export goValidatorInitialize
func goValidatorInitialize(userData unsafe.Pointer, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(Validator)

	if !ok {
		return 1
	}
	err := impl.Initialize()
	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0
}

//export goValidatorShutdown
func goValidatorShutdown(userData unsafe.Pointer, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(Validator)

	if !ok {
		return 1
	}
	err := impl.Shutdown()
	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0
}

//export goValidatorFreeUserData
func goValidatorFreeUserData(userData unsafe.Pointer) {

	// No-op to avoid cleanup-queue panics. Handles cleaned in Unregister().
}

//export goValidatorFreeString
func goValidatorFreeString(ptr *C.char) {
	if ptr != nil {
		C.free(unsafe.Pointer(ptr))
	}
}

// RegisterValidator registers a Validator implementation with the C runtime.
func RegisterValidator(impl Validator) error {
	handle := cgo.NewHandle(impl)
	// Build the C vtable  DEBUG:c_vtable_struct=KREUZBERGKreuzbergValidatorVTable
	vtable := C.KREUZBERGKreuzbergValidatorVTable{
		validate: (*[0]byte)(unsafe.Pointer(C.goValidatorValidate)),
		should_validate: (*[0]byte)(unsafe.Pointer(C.goValidatorShouldValidate)),
		priority: (*[0]byte)(unsafe.Pointer(C.goValidatorPriority)),
		name_fn: (*[0]byte)(unsafe.Pointer(C.goValidatorName)),
		version_fn: (*[0]byte)(unsafe.Pointer(C.goValidatorVersion)),
		initialize_fn: (*[0]byte)(unsafe.Pointer(C.goValidatorInitialize)),
		shutdown_fn: (*[0]byte)(unsafe.Pointer(C.goValidatorShutdown)),
		free_string: (*[0]byte)(unsafe.Pointer(C.goValidatorFreeString)),
		free_user_data: (*[0]byte)(unsafe.Pointer(C.goValidatorFreeUserData)),
	}

	// Call C registration
	cName := C.CString(impl.Name())
	defer C.free(unsafe.Pointer(cName))

	var cErr *C.char
	rc := C.kreuzberg_register_validator(
		cName,
		vtable,
		unsafe.Pointer(uintptr(handle)),
		&cErr,
	)

	if rc != 0 {
		msg := "failed to register Validator"
		if cErr != nil {
			msg = C.GoString(cErr)
			C.kreuzberg_free_string(cErr)
		}
		handle.Delete()
		return fmt.Errorf("%s", msg)
	}

	// Store handle by name for later cleanup on unregister
	validatorRegistry.store(impl.Name(), handle)
	return nil
}

// UnregisterValidator unregisters a Validator implementation.
func UnregisterValidator(name string) error {
	cName := C.CString(name)
	defer C.free(unsafe.Pointer(cName))
	var cErr *C.char
	rc := C.kreuzberg_unregister_validator(cName, &cErr)

	if rc != 0 {
	msg := "failed to unregister Validator"
	if cErr != nil {
		msg = C.GoString(cErr)
		C.kreuzberg_free_string(cErr)
	}
	return fmt.Errorf("%s", msg)
	}

	// Delete the handle now that Rust has unregistered the plugin
	validatorRegistry.delete(name)
	return nil
}

// ClearValidators removes all registered Validator implementations.
func ClearValidators() error {
	var cErr *C.char
	rc := C.kreuzberg_clear_validator(&cErr)

	if rc != 0 {
		msg := "failed to clear Validator plugins"
		if cErr != nil {
			msg = C.GoString(cErr)
			C.free(unsafe.Pointer(cErr))
		}
		return fmt.Errorf("%s", msg)
	}

	// Delete all handles now that Rust has cleared all plugins
	validatorRegistry.clear()
	return nil
}

// EmbeddingBackend defines the Go interface for the EmbeddingBackend trait.
type EmbeddingBackend interface {
	// Name returns the plugin name.
	Name() string
	// Version returns the plugin version.
	Version() string
	// Initialize is called when the plugin is loaded.
	Initialize() error
	// Shutdown is called when the plugin is unloaded.
	Shutdown() error
	// dimensions
	Dimensions() uint

	// embed
	Embed(texts []string) ([][]float32, error)

}

//export goEmbeddingBackendDimensions
func goEmbeddingBackendDimensions(
	userData unsafe.Pointer,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(EmbeddingBackend)

	if !ok {
		return 1  // error: invalid handle
	}

	// Call the method
		result := impl.Dimensions()

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goEmbeddingBackendEmbed
func goEmbeddingBackendEmbed(
	userData unsafe.Pointer,
	texts *C.char,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(EmbeddingBackend)

	if !ok {
		return 1  // error: invalid handle
	}

		var goTexts []string
		if texts != nil {
			json.Unmarshal([]byte(C.GoString(texts)), &goTexts)

	}

	// Call the method
		result, err := impl.Embed(goTexts)

	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goEmbeddingBackendName
func goEmbeddingBackendName(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(EmbeddingBackend)

	if !ok {
		return 1
	}
	name := impl.Name()
	cName := C.CString(name)
	*outResult = cName
	return 0
}

//export goEmbeddingBackendVersion
func goEmbeddingBackendVersion(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(EmbeddingBackend)

	if !ok {
		return 1
	}
	version := impl.Version()
	cVersion := C.CString(version)
	*outResult = cVersion
	return 0
}

//export goEmbeddingBackendInitialize
func goEmbeddingBackendInitialize(userData unsafe.Pointer, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(EmbeddingBackend)

	if !ok {
		return 1
	}
	err := impl.Initialize()
	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0
}

//export goEmbeddingBackendShutdown
func goEmbeddingBackendShutdown(userData unsafe.Pointer, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(EmbeddingBackend)

	if !ok {
		return 1
	}
	err := impl.Shutdown()
	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0
}

//export goEmbeddingBackendFreeUserData
func goEmbeddingBackendFreeUserData(userData unsafe.Pointer) {

	// No-op to avoid cleanup-queue panics. Handles cleaned in Unregister().
}

//export goEmbeddingBackendFreeString
func goEmbeddingBackendFreeString(ptr *C.char) {
	if ptr != nil {
		C.free(unsafe.Pointer(ptr))
	}
}

// RegisterEmbeddingBackend registers a EmbeddingBackend implementation with the C runtime.
func RegisterEmbeddingBackend(impl EmbeddingBackend) error {
	handle := cgo.NewHandle(impl)
	// Build the C vtable  DEBUG:c_vtable_struct=KREUZBERGKreuzbergEmbeddingBackendVTable
	vtable := C.KREUZBERGKreuzbergEmbeddingBackendVTable{
		dimensions: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendDimensions)),
		embed: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendEmbed)),
		name_fn: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendName)),
		version_fn: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendVersion)),
		initialize_fn: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendInitialize)),
		shutdown_fn: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendShutdown)),
		free_string: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendFreeString)),
		free_user_data: (*[0]byte)(unsafe.Pointer(C.goEmbeddingBackendFreeUserData)),
	}

	// Call C registration
	cName := C.CString(impl.Name())
	defer C.free(unsafe.Pointer(cName))

	var cErr *C.char
	rc := C.kreuzberg_register_embedding_backend(
		cName,
		vtable,
		unsafe.Pointer(uintptr(handle)),
		&cErr,
	)

	if rc != 0 {
		msg := "failed to register EmbeddingBackend"
		if cErr != nil {
			msg = C.GoString(cErr)
			C.kreuzberg_free_string(cErr)
		}
		handle.Delete()
		return fmt.Errorf("%s", msg)
	}

	// Store handle by name for later cleanup on unregister
	embedding_backendRegistry.store(impl.Name(), handle)
	return nil
}

// UnregisterEmbeddingBackend unregisters a EmbeddingBackend implementation.
func UnregisterEmbeddingBackend(name string) error {
	cName := C.CString(name)
	defer C.free(unsafe.Pointer(cName))
	var cErr *C.char
	rc := C.kreuzberg_unregister_embedding_backend(cName, &cErr)

	if rc != 0 {
	msg := "failed to unregister EmbeddingBackend"
	if cErr != nil {
		msg = C.GoString(cErr)
		C.kreuzberg_free_string(cErr)
	}
	return fmt.Errorf("%s", msg)
	}

	// Delete the handle now that Rust has unregistered the plugin
	embedding_backendRegistry.delete(name)
	return nil
}

// ClearEmbeddingBackends removes all registered EmbeddingBackend implementations.
func ClearEmbeddingBackends() error {
	var cErr *C.char
	rc := C.kreuzberg_clear_embedding_backend(&cErr)

	if rc != 0 {
		msg := "failed to clear EmbeddingBackend plugins"
		if cErr != nil {
			msg = C.GoString(cErr)
			C.free(unsafe.Pointer(cErr))
		}
		return fmt.Errorf("%s", msg)
	}

	// Delete all handles now that Rust has cleared all plugins
	embedding_backendRegistry.clear()
	return nil
}

// DocumentExtractor defines the Go interface for the DocumentExtractor trait.
type DocumentExtractor interface {
	// Name returns the plugin name.
	Name() string
	// Version returns the plugin version.
	Version() string
	// Initialize is called when the plugin is loaded.
	Initialize() error
	// Shutdown is called when the plugin is unloaded.
	Shutdown() error
	// extract_bytes
	ExtractBytes(content []byte, mime_type string, config ExtractionConfig) (json.RawMessage, error)

	// extract_file
	ExtractFile(path string, mime_type string, config ExtractionConfig) (json.RawMessage, error)

	// supported_mime_types
	SupportedMimeTypes() []string

	// priority
	Priority() int32

	// can_handle
	CanHandle(_path string, _mime_type string) bool

}

//export goDocumentExtractorExtractBytes
func goDocumentExtractorExtractBytes(
	userData unsafe.Pointer,
	content *C.uint8_t,
	contentLen C.size_t,
	mime_type *C.char,
	config *C.char,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(DocumentExtractor)

	if !ok {
		return 1  // error: invalid handle
	}

	var goContent []byte
	if content != nil {
		goContent = unsafe.Slice((*byte)(unsafe.Pointer(content)), int(contentLen))
	}

		goMime_type := C.GoString(mime_type)

		var goConfig ExtractionConfig
		if config != nil {
			json.Unmarshal([]byte(C.GoString(config)), &goConfig)

	}

	// Call the method
		result, err := impl.ExtractBytes(goContent, goMime_type, goConfig)

	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	cResult := C.CString(string(result))
	*outResult = cResult
	return 0  // success
}

//export goDocumentExtractorExtractFile
func goDocumentExtractorExtractFile(
	userData unsafe.Pointer,
	path *C.char,
	mime_type *C.char,
	config *C.char,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(DocumentExtractor)

	if !ok {
		return 1  // error: invalid handle
	}

		goPath := C.GoString(path)

		goMime_type := C.GoString(mime_type)

		var goConfig ExtractionConfig
		if config != nil {
			json.Unmarshal([]byte(C.GoString(config)), &goConfig)

	}

	// Call the method
		result, err := impl.ExtractFile(goPath, goMime_type, goConfig)

	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	cResult := C.CString(string(result))
	*outResult = cResult
	return 0  // success
}

//export goDocumentExtractorSupportedMimeTypes
func goDocumentExtractorSupportedMimeTypes(
	userData unsafe.Pointer,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(DocumentExtractor)

	if !ok {
		return 1  // error: invalid handle
	}

	// Call the method
		result := impl.SupportedMimeTypes()

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goDocumentExtractorPriority
func goDocumentExtractorPriority(
	userData unsafe.Pointer,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(DocumentExtractor)

	if !ok {
		return 1  // error: invalid handle
	}

	// Call the method
		result := impl.Priority()

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goDocumentExtractorCanHandle
func goDocumentExtractorCanHandle(
	userData unsafe.Pointer,
	_path *C.char,
	_mime_type *C.char,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(DocumentExtractor)

	if !ok {
		return 1  // error: invalid handle
	}

		go_path := C.GoString(_path)

		go_mime_type := C.GoString(_mime_type)

	// Call the method
		result := impl.CanHandle(go_path, go_mime_type)

	jsonBytes, _ := json.Marshal(result)
	cResult := C.CString(string(jsonBytes))
	*outResult = cResult
	return 0  // success
}

//export goDocumentExtractorName
func goDocumentExtractorName(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(DocumentExtractor)

	if !ok {
		return 1
	}
	name := impl.Name()
	cName := C.CString(name)
	*outResult = cName
	return 0
}

//export goDocumentExtractorVersion
func goDocumentExtractorVersion(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(DocumentExtractor)

	if !ok {
		return 1
	}
	version := impl.Version()
	cVersion := C.CString(version)
	*outResult = cVersion
	return 0
}

//export goDocumentExtractorInitialize
func goDocumentExtractorInitialize(userData unsafe.Pointer, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(DocumentExtractor)

	if !ok {
		return 1
	}
	err := impl.Initialize()
	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0
}

//export goDocumentExtractorShutdown
func goDocumentExtractorShutdown(userData unsafe.Pointer, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(DocumentExtractor)

	if !ok {
		return 1
	}
	err := impl.Shutdown()
	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0
}

//export goDocumentExtractorFreeUserData
func goDocumentExtractorFreeUserData(userData unsafe.Pointer) {

	// No-op to avoid cleanup-queue panics. Handles cleaned in Unregister().
}

//export goDocumentExtractorFreeString
func goDocumentExtractorFreeString(ptr *C.char) {
	if ptr != nil {
		C.free(unsafe.Pointer(ptr))
	}
}

// RegisterDocumentExtractor registers a DocumentExtractor implementation with the C runtime.
func RegisterDocumentExtractor(impl DocumentExtractor) error {
	handle := cgo.NewHandle(impl)
	// Build the C vtable  DEBUG:c_vtable_struct=KREUZBERGKreuzbergDocumentExtractorVTable
	vtable := C.KREUZBERGKreuzbergDocumentExtractorVTable{
		extract_bytes: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorExtractBytes)),
		extract_file: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorExtractFile)),
		supported_mime_types: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorSupportedMimeTypes)),
		priority: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorPriority)),
		can_handle: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorCanHandle)),
		name_fn: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorName)),
		version_fn: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorVersion)),
		initialize_fn: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorInitialize)),
		shutdown_fn: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorShutdown)),
		free_string: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorFreeString)),
		free_user_data: (*[0]byte)(unsafe.Pointer(C.goDocumentExtractorFreeUserData)),
	}

	// Call C registration
	cName := C.CString(impl.Name())
	defer C.free(unsafe.Pointer(cName))

	var cErr *C.char
	rc := C.kreuzberg_register_document_extractor(
		cName,
		vtable,
		unsafe.Pointer(uintptr(handle)),
		&cErr,
	)

	if rc != 0 {
		msg := "failed to register DocumentExtractor"
		if cErr != nil {
			msg = C.GoString(cErr)
			C.kreuzberg_free_string(cErr)
		}
		handle.Delete()
		return fmt.Errorf("%s", msg)
	}

	// Store handle by name for later cleanup on unregister
	document_extractorRegistry.store(impl.Name(), handle)
	return nil
}

// UnregisterDocumentExtractor unregisters a DocumentExtractor implementation.
func UnregisterDocumentExtractor(name string) error {
	cName := C.CString(name)
	defer C.free(unsafe.Pointer(cName))
	var cErr *C.char
	rc := C.kreuzberg_unregister_document_extractor(cName, &cErr)

	if rc != 0 {
	msg := "failed to unregister DocumentExtractor"
	if cErr != nil {
		msg = C.GoString(cErr)
		C.kreuzberg_free_string(cErr)
	}
	return fmt.Errorf("%s", msg)
	}

	// Delete the handle now that Rust has unregistered the plugin
	document_extractorRegistry.delete(name)
	return nil
}

// ClearDocumentExtractors removes all registered DocumentExtractor implementations.
func ClearDocumentExtractors() error {
	var cErr *C.char
	rc := C.kreuzberg_clear_document_extractor(&cErr)

	if rc != 0 {
		msg := "failed to clear DocumentExtractor plugins"
		if cErr != nil {
			msg = C.GoString(cErr)
			C.free(unsafe.Pointer(cErr))
		}
		return fmt.Errorf("%s", msg)
	}

	// Delete all handles now that Rust has cleared all plugins
	document_extractorRegistry.clear()
	return nil
}

// Renderer defines the Go interface for the Renderer trait.
type Renderer interface {
	// Name returns the plugin name.
	Name() string
	// Version returns the plugin version.
	Version() string
	// Initialize is called when the plugin is loaded.
	Initialize() error
	// Shutdown is called when the plugin is unloaded.
	Shutdown() error
	// render
	Render(doc json.RawMessage) (string, error)

}

//export goRendererRender
func goRendererRender(
	userData unsafe.Pointer,
	doc *C.char,
	outResult **C.char,
	outError **C.char,
) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(Renderer)

	if !ok {
		return 1  // error: invalid handle
	}

	var goDoc json.RawMessage
		if doc != nil {
		goDoc = json.RawMessage(C.GoString(doc))
	}

	// Call the method
		result, err := impl.Render(goDoc)

	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	cResult := C.CString(result)
	*outResult = cResult
	return 0  // success
}

//export goRendererName
func goRendererName(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(Renderer)

	if !ok {
		return 1
	}
	name := impl.Name()
	cName := C.CString(name)
	*outResult = cName
	return 0
}

//export goRendererVersion
func goRendererVersion(userData unsafe.Pointer, outResult **C.char, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(Renderer)

	if !ok {
		return 1
	}
	version := impl.Version()
	cVersion := C.CString(version)
	*outResult = cVersion
	return 0
}

//export goRendererInitialize
func goRendererInitialize(userData unsafe.Pointer, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(Renderer)

	if !ok {
		return 1
	}
	err := impl.Initialize()
	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0
}

//export goRendererShutdown
func goRendererShutdown(userData unsafe.Pointer, outError **C.char) C.int32_t {

	handle := cgo.Handle(uintptr(unsafe.Pointer(userData)))
	impl, ok := handle.Value().(Renderer)

	if !ok {
		return 1
	}
	err := impl.Shutdown()
	if err != nil {
		cErr := C.CString(err.Error())
		*outError = cErr
		return 1
	}
	return 0
}

//export goRendererFreeUserData
func goRendererFreeUserData(userData unsafe.Pointer) {

	// No-op to avoid cleanup-queue panics. Handles cleaned in Unregister().
}

//export goRendererFreeString
func goRendererFreeString(ptr *C.char) {
	if ptr != nil {
		C.free(unsafe.Pointer(ptr))
	}
}

// RegisterRenderer registers a Renderer implementation with the C runtime.
func RegisterRenderer(impl Renderer) error {
	handle := cgo.NewHandle(impl)
	// Build the C vtable  DEBUG:c_vtable_struct=KREUZBERGKreuzbergRendererVTable
	vtable := C.KREUZBERGKreuzbergRendererVTable{
		render: (*[0]byte)(unsafe.Pointer(C.goRendererRender)),
		name_fn: (*[0]byte)(unsafe.Pointer(C.goRendererName)),
		version_fn: (*[0]byte)(unsafe.Pointer(C.goRendererVersion)),
		initialize_fn: (*[0]byte)(unsafe.Pointer(C.goRendererInitialize)),
		shutdown_fn: (*[0]byte)(unsafe.Pointer(C.goRendererShutdown)),
		free_string: (*[0]byte)(unsafe.Pointer(C.goRendererFreeString)),
		free_user_data: (*[0]byte)(unsafe.Pointer(C.goRendererFreeUserData)),
	}

	// Call C registration
	cName := C.CString(impl.Name())
	defer C.free(unsafe.Pointer(cName))

	var cErr *C.char
	rc := C.kreuzberg_register_renderer(
		cName,
		vtable,
		unsafe.Pointer(uintptr(handle)),
		&cErr,
	)

	if rc != 0 {
		msg := "failed to register Renderer"
		if cErr != nil {
			msg = C.GoString(cErr)
			C.kreuzberg_free_string(cErr)
		}
		handle.Delete()
		return fmt.Errorf("%s", msg)
	}

	// Store handle by name for later cleanup on unregister
	rendererRegistry.store(impl.Name(), handle)
	return nil
}

// UnregisterRenderer unregisters a Renderer implementation.
func UnregisterRenderer(name string) error {
	cName := C.CString(name)
	defer C.free(unsafe.Pointer(cName))
	var cErr *C.char
	rc := C.kreuzberg_unregister_renderer(cName, &cErr)

	if rc != 0 {
	msg := "failed to unregister Renderer"
	if cErr != nil {
		msg = C.GoString(cErr)
		C.kreuzberg_free_string(cErr)
	}
	return fmt.Errorf("%s", msg)
	}

	// Delete the handle now that Rust has unregistered the plugin
	rendererRegistry.delete(name)
	return nil
}

// ClearRenderers removes all registered Renderer implementations.
func ClearRenderers() error {
	var cErr *C.char
	rc := C.kreuzberg_clear_renderer(&cErr)

	if rc != 0 {
		msg := "failed to clear Renderer plugins"
		if cErr != nil {
			msg = C.GoString(cErr)
			C.free(unsafe.Pointer(cErr))
		}
		return fmt.Errorf("%s", msg)
	}

	// Delete all handles now that Rust has cleared all plugins
	rendererRegistry.clear()
	return nil
}
