// 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
#nullable enable

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Kreuzberg;

/// <summary>
/// Configuration for PaddleOCR backend.
///
/// Configures PaddleOCR text detection and recognition with multi-language support.
/// Uses a builder pattern for convenient configuration.
/// </summary>
public sealed record PaddleOcrConfig
{
    /// <summary>
    /// Language code (e.g., "en", "ch", "jpn", "kor", "deu", "fra")
    /// </summary>
    [JsonPropertyName("language")]
    public string Language { get; init; } = "";

    /// <summary>
    /// Optional custom cache directory for model files
    /// </summary>
    [JsonPropertyName("cache_dir")]
    public string? CacheDir { get; init; } = null;

    /// <summary>
    /// Enable angle classification for rotated text (default: false).
    /// Can misfire on short text regions, rotating crops incorrectly before recognition.
    /// </summary>
    [JsonPropertyName("use_angle_cls")]
    public bool UseAngleCls { get; init; } = false;

    /// <summary>
    /// Enable table structure detection (default: false)
    /// </summary>
    [JsonPropertyName("enable_table_detection")]
    public bool EnableTableDetection { get; init; } = false;

    /// <summary>
    /// Database threshold for text detection (default: 0.3)
    /// Range: 0.0-1.0, higher values require more confident detections
    /// </summary>
    [JsonPropertyName("det_db_thresh")]
    public float DetDbThresh { get; init; } = 0.0f;

    /// <summary>
    /// Box threshold for text bounding box refinement (default: 0.5)
    /// Range: 0.0-1.0
    /// </summary>
    [JsonPropertyName("det_db_box_thresh")]
    public float DetDbBoxThresh { get; init; } = 0.0f;

    /// <summary>
    /// Unclip ratio for expanding text bounding boxes (default: 1.6)
    /// Controls the expansion of detected text regions
    /// </summary>
    [JsonPropertyName("det_db_unclip_ratio")]
    public float DetDbUnclipRatio { get; init; } = 0.0f;

    /// <summary>
    /// Maximum side length for detection image (default: 960)
    /// Larger images may be resized to this limit for faster inference
    /// </summary>
    [JsonPropertyName("det_limit_side_len")]
    public uint DetLimitSideLen { get; init; } = 0;

    /// <summary>
    /// Batch size for recognition inference (default: 6)
    /// Number of text regions to process simultaneously
    /// </summary>
    [JsonPropertyName("rec_batch_num")]
    public uint RecBatchNum { get; init; } = 0;

    /// <summary>
    /// Padding in pixels added around the image before detection (default: 10).
    /// Large values can include surrounding content like table gridlines.
    /// </summary>
    [JsonPropertyName("padding")]
    public uint Padding { get; init; } = 0;

    /// <summary>
    /// Minimum recognition confidence score for text lines (default: 0.5).
    /// Text regions with recognition confidence below this threshold are discarded.
    /// Matches PaddleOCR Python's `drop_score` parameter.
    /// Range: 0.0-1.0
    /// </summary>
    [JsonPropertyName("drop_score")]
    public float DropScore { get; init; } = 0.0f;

    /// <summary>
    /// Model tier controlling detection/recognition model size and accuracy trade-off.
    /// - `"mobile"` (default): Lightweight models (~4.5MB detection, ~16.5MB recognition), fast download and inference
    /// - `"server"`: Large, high-accuracy models (~88MB detection, ~84MB recognition), best for GPU or complex documents
    /// </summary>
    [JsonPropertyName("model_tier")]
    public string ModelTier { get; init; } = "";


    /// <summary>
    /// Parse a <see cref="PaddleOcrConfig"/> from a JSON string.
    /// </summary>
    /// <exception cref="KreuzbergException">When the JSON cannot be deserialised.</exception>
    public static PaddleOcrConfig FromJson(string json)
    {
        try
        {
            return JsonSerializer.Deserialize<PaddleOcrConfig>(json, JsonOptions)
                ?? throw new KreuzbergException($"Failed to parse PaddleOcrConfig from JSON: deserializer returned null");
        }
        catch (KreuzbergException)
        {
            throw;
        }
        catch (Exception e)
        {
            throw new KreuzbergException($"Failed to parse PaddleOcrConfig from JSON: {e.Message}", e);
        }
    }

    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
        Converters = { new JsonStringEnumConverter(JsonNamingPolicy.SnakeCaseLower) },
    };

    /// <summary>Options for serializing config/input objects to FFI. Strips nulls
    /// (nullable C# fields default to null and would override required Rust fields with
    /// non-deserialisable nulls) but preserves explicit false/0 so caller intent is kept.</summary>
    private static readonly JsonSerializerOptions JsonSerializationOptions = new()
    {
        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
        Converters = { new JsonStringEnumConverter(JsonNamingPolicy.SnakeCaseLower) },
    };

    /// <summary>
    /// Sets a custom cache directory for model files.
    /// </summary>
    public PaddleOcrConfig WithCacheDir(string path)
    {
        var selfJson = JsonSerializer.Serialize(this, JsonSerializationOptions);
var selfHandle = NativeMethods.PaddleOcrConfigFromJson(selfJson);
        try
        {
            var nativeResult = NativeMethods.PaddleOcrConfigWithCacheDir(selfHandle, path);
var jsonPtr = NativeMethods.PaddleOcrConfigToJson(nativeResult);
var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
NativeMethods.FreeString(jsonPtr);
NativeMethods.PaddleOcrConfigFree(nativeResult);
return JsonSerializer.Deserialize<PaddleOcrConfig>(json ?? "null", JsonOptions)!;
}
finally
        {
            NativeMethods.PaddleOcrConfigFree(selfHandle);
}
    }

    /// <summary>
    /// Enables or disables table structure detection.
    /// </summary>
    public PaddleOcrConfig WithTableDetection(bool enable)
    {
        var selfJson = JsonSerializer.Serialize(this, JsonSerializationOptions);
var selfHandle = NativeMethods.PaddleOcrConfigFromJson(selfJson);
        try
        {
            var nativeResult = NativeMethods.PaddleOcrConfigWithTableDetection(selfHandle, enable);
var jsonPtr = NativeMethods.PaddleOcrConfigToJson(nativeResult);
var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
NativeMethods.FreeString(jsonPtr);
NativeMethods.PaddleOcrConfigFree(nativeResult);
return JsonSerializer.Deserialize<PaddleOcrConfig>(json ?? "null", JsonOptions)!;
}
finally
        {
            NativeMethods.PaddleOcrConfigFree(selfHandle);
}
    }

    /// <summary>
    /// Enables or disables angle classification for rotated text.
    /// </summary>
    public PaddleOcrConfig WithAngleCls(bool enable)
    {
        var selfJson = JsonSerializer.Serialize(this, JsonSerializationOptions);
var selfHandle = NativeMethods.PaddleOcrConfigFromJson(selfJson);
        try
        {
            var nativeResult = NativeMethods.PaddleOcrConfigWithAngleCls(selfHandle, enable);
var jsonPtr = NativeMethods.PaddleOcrConfigToJson(nativeResult);
var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
NativeMethods.FreeString(jsonPtr);
NativeMethods.PaddleOcrConfigFree(nativeResult);
return JsonSerializer.Deserialize<PaddleOcrConfig>(json ?? "null", JsonOptions)!;
}
finally
        {
            NativeMethods.PaddleOcrConfigFree(selfHandle);
}
    }

    /// <summary>
    /// Sets the database threshold for text detection.
    /// </summary>
    public PaddleOcrConfig WithDetDbThresh(float threshold)
    {
        var selfJson = JsonSerializer.Serialize(this, JsonSerializationOptions);
var selfHandle = NativeMethods.PaddleOcrConfigFromJson(selfJson);
        try
        {
            var nativeResult = NativeMethods.PaddleOcrConfigWithDetDbThresh(selfHandle, threshold);
var jsonPtr = NativeMethods.PaddleOcrConfigToJson(nativeResult);
var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
NativeMethods.FreeString(jsonPtr);
NativeMethods.PaddleOcrConfigFree(nativeResult);
return JsonSerializer.Deserialize<PaddleOcrConfig>(json ?? "null", JsonOptions)!;
}
finally
        {
            NativeMethods.PaddleOcrConfigFree(selfHandle);
}
    }

    /// <summary>
    /// Sets the box threshold for text bounding box refinement.
    /// </summary>
    public PaddleOcrConfig WithDetDbBoxThresh(float threshold)
    {
        var selfJson = JsonSerializer.Serialize(this, JsonSerializationOptions);
var selfHandle = NativeMethods.PaddleOcrConfigFromJson(selfJson);
        try
        {
            var nativeResult = NativeMethods.PaddleOcrConfigWithDetDbBoxThresh(selfHandle, threshold);
var jsonPtr = NativeMethods.PaddleOcrConfigToJson(nativeResult);
var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
NativeMethods.FreeString(jsonPtr);
NativeMethods.PaddleOcrConfigFree(nativeResult);
return JsonSerializer.Deserialize<PaddleOcrConfig>(json ?? "null", JsonOptions)!;
}
finally
        {
            NativeMethods.PaddleOcrConfigFree(selfHandle);
}
    }

    /// <summary>
    /// Sets the unclip ratio for expanding text bounding boxes.
    /// </summary>
    public PaddleOcrConfig WithDetDbUnclipRatio(float ratio)
    {
        var selfJson = JsonSerializer.Serialize(this, JsonSerializationOptions);
var selfHandle = NativeMethods.PaddleOcrConfigFromJson(selfJson);
        try
        {
            var nativeResult = NativeMethods.PaddleOcrConfigWithDetDbUnclipRatio(selfHandle, ratio);
var jsonPtr = NativeMethods.PaddleOcrConfigToJson(nativeResult);
var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
NativeMethods.FreeString(jsonPtr);
NativeMethods.PaddleOcrConfigFree(nativeResult);
return JsonSerializer.Deserialize<PaddleOcrConfig>(json ?? "null", JsonOptions)!;
}
finally
        {
            NativeMethods.PaddleOcrConfigFree(selfHandle);
}
    }

    /// <summary>
    /// Sets the maximum side length for detection images.
    /// </summary>
    public PaddleOcrConfig WithDetLimitSideLen(uint length)
    {
        var selfJson = JsonSerializer.Serialize(this, JsonSerializationOptions);
var selfHandle = NativeMethods.PaddleOcrConfigFromJson(selfJson);
        try
        {
            var nativeResult = NativeMethods.PaddleOcrConfigWithDetLimitSideLen(selfHandle, length);
var jsonPtr = NativeMethods.PaddleOcrConfigToJson(nativeResult);
var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
NativeMethods.FreeString(jsonPtr);
NativeMethods.PaddleOcrConfigFree(nativeResult);
return JsonSerializer.Deserialize<PaddleOcrConfig>(json ?? "null", JsonOptions)!;
}
finally
        {
            NativeMethods.PaddleOcrConfigFree(selfHandle);
}
    }

    /// <summary>
    /// Sets the batch size for recognition inference.
    /// </summary>
    public PaddleOcrConfig WithRecBatchNum(uint batchSize)
    {
        var selfJson = JsonSerializer.Serialize(this, JsonSerializationOptions);
var selfHandle = NativeMethods.PaddleOcrConfigFromJson(selfJson);
        try
        {
            var nativeResult = NativeMethods.PaddleOcrConfigWithRecBatchNum(selfHandle, batchSize);
var jsonPtr = NativeMethods.PaddleOcrConfigToJson(nativeResult);
var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
NativeMethods.FreeString(jsonPtr);
NativeMethods.PaddleOcrConfigFree(nativeResult);
return JsonSerializer.Deserialize<PaddleOcrConfig>(json ?? "null", JsonOptions)!;
}
finally
        {
            NativeMethods.PaddleOcrConfigFree(selfHandle);
}
    }

    /// <summary>
    /// Sets the minimum recognition confidence threshold.
    /// </summary>
    public PaddleOcrConfig WithDropScore(float score)
    {
        var selfJson = JsonSerializer.Serialize(this, JsonSerializationOptions);
var selfHandle = NativeMethods.PaddleOcrConfigFromJson(selfJson);
        try
        {
            var nativeResult = NativeMethods.PaddleOcrConfigWithDropScore(selfHandle, score);
var jsonPtr = NativeMethods.PaddleOcrConfigToJson(nativeResult);
var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
NativeMethods.FreeString(jsonPtr);
NativeMethods.PaddleOcrConfigFree(nativeResult);
return JsonSerializer.Deserialize<PaddleOcrConfig>(json ?? "null", JsonOptions)!;
}
finally
        {
            NativeMethods.PaddleOcrConfigFree(selfHandle);
}
    }

    /// <summary>
    /// Sets padding in pixels added around images before detection.
    /// </summary>
    public PaddleOcrConfig WithPadding(uint padding)
    {
        var selfJson = JsonSerializer.Serialize(this, JsonSerializationOptions);
var selfHandle = NativeMethods.PaddleOcrConfigFromJson(selfJson);
        try
        {
            var nativeResult = NativeMethods.PaddleOcrConfigWithPadding(selfHandle, padding);
var jsonPtr = NativeMethods.PaddleOcrConfigToJson(nativeResult);
var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
NativeMethods.FreeString(jsonPtr);
NativeMethods.PaddleOcrConfigFree(nativeResult);
return JsonSerializer.Deserialize<PaddleOcrConfig>(json ?? "null", JsonOptions)!;
}
finally
        {
            NativeMethods.PaddleOcrConfigFree(selfHandle);
}
    }

    /// <summary>
    /// Sets the model tier controlling detection/recognition model size.
    /// </summary>
    public PaddleOcrConfig WithModelTier(string tier)
    {
        var selfJson = JsonSerializer.Serialize(this, JsonSerializationOptions);
var selfHandle = NativeMethods.PaddleOcrConfigFromJson(selfJson);
        try
        {
            var nativeResult = NativeMethods.PaddleOcrConfigWithModelTier(selfHandle, tier);
var jsonPtr = NativeMethods.PaddleOcrConfigToJson(nativeResult);
var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
NativeMethods.FreeString(jsonPtr);
NativeMethods.PaddleOcrConfigFree(nativeResult);
return JsonSerializer.Deserialize<PaddleOcrConfig>(json ?? "null", JsonOptions)!;
}
finally
        {
            NativeMethods.PaddleOcrConfigFree(selfHandle);
}
    }

    /// <summary>
    /// Creates a default configuration with English language support.
    /// </summary>
    public static PaddleOcrConfig Default()
    {
        var nativeResult = NativeMethods.PaddleOcrConfigDefault();
        var jsonPtr = NativeMethods.PaddleOcrConfigToJson(nativeResult);
        var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
        NativeMethods.FreeString(jsonPtr);
        NativeMethods.PaddleOcrConfigFree(nativeResult);
        return JsonSerializer.Deserialize<PaddleOcrConfig>(json ?? "null", JsonOptions)!;
    }
}
