// 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>
/// Image extraction configuration.
/// </summary>
public sealed record ImageExtractionConfig
{
    /// <summary>
    /// Extract images from documents
    /// </summary>
    [JsonPropertyName("extract_images")]
    public bool ExtractImages { get; init; } = true;

    /// <summary>
    /// Target DPI for image normalization
    /// </summary>
    [JsonPropertyName("target_dpi")]
    public int TargetDpi { get; init; } = 300;

    /// <summary>
    /// Maximum dimension for images (width or height)
    /// </summary>
    [JsonPropertyName("max_image_dimension")]
    public int MaxImageDimension { get; init; } = 4096;

    /// <summary>
    /// Whether to inject image reference placeholders into markdown output.
    /// When `true` (default), image references like `![Image 1](embedded:p1_i0)`
    /// are appended to the markdown. Set to `false` to extract images as data
    /// without polluting the markdown output.
    /// </summary>
    [JsonPropertyName("inject_placeholders")]
    public bool InjectPlaceholders { get; init; } = true;

    /// <summary>
    /// Automatically adjust DPI based on image content
    /// </summary>
    [JsonPropertyName("auto_adjust_dpi")]
    public bool AutoAdjustDpi { get; init; } = true;

    /// <summary>
    /// Minimum DPI threshold
    /// </summary>
    [JsonPropertyName("min_dpi")]
    public int MinDpi { get; init; } = 72;

    /// <summary>
    /// Maximum DPI threshold
    /// </summary>
    [JsonPropertyName("max_dpi")]
    public int MaxDpi { get; init; } = 600;

    /// <summary>
    /// Maximum number of image objects to extract per PDF page.
    ///
    /// Some PDFs (e.g. technical diagrams stored as thousands of raster fragments)
    /// can trigger extremely long or indefinite extraction times when every image
    /// object on a dense page is decoded individually via the PDF extractor. Setting this
    /// limit causes kreuzberg to stop collecting individual images once the count
    /// per page reaches the cap and emit a warning instead.
    ///
    /// `None` (default) means no limit — all images are extracted.
    /// </summary>
    [JsonPropertyName("max_images_per_page")]
    public uint? MaxImagesPerPage { get; init; } = null;

    /// <summary>
    /// When `true` (default), extracted images are classified by kind and grouped
    /// into clusters where they appear to belong to one figure.
    /// </summary>
    [JsonPropertyName("classify")]
    public bool Classify { get; init; } = true;

    /// <summary>
    /// When `true`, full-page renders produced during OCR preprocessing are captured
    /// and returned as `ImageKind.PageRaster` entries in `ExtractionResult.images`.
    ///
    /// **PDF + OCR only.** No rasters are captured for non-PDF inputs or when the
    /// document-level OCR bypass is active (whole-document backend). When OCR is
    /// enabled and this flag is set but the active backend skips per-page rendering,
    /// a `ProcessingWarning` is emitted in `ExtractionResult.processing_warnings`.
    ///
    /// Defaults to `false`. Enable when downstream consumers need page thumbnails
    /// (e.g. citation previews, visual grounding).
    /// </summary>
    [JsonPropertyName("include_page_rasters")]
    public bool IncludePageRasters { get; init; } = false;

    /// <summary>
    /// Run OCR on extracted images and include the recognized text in the document content.
    ///
    /// When `true` (default) and `ExtractionConfig.ocr` is configured, extracted images
    /// are processed with the configured OCR backend. Set to `false` to extract images
    /// without OCR processing, even when OCR is enabled.
    /// </summary>
    [JsonPropertyName("run_ocr_on_images")]
    public bool RunOcrOnImages { get; init; } = true;

    /// <summary>
    /// When `true`, image OCR results are rendered as plain text without the
    /// `![...](...)` markdown placeholder. Only takes effect when `run_ocr_on_images`
    /// is also `true`.
    /// </summary>
    [JsonPropertyName("ocr_text_only")]
    public bool OcrTextOnly { get; init; } = false;

    /// <summary>
    /// When `true` and `ocr_text_only` is `false`, append the OCR text after
    /// the image placeholder in the rendered output.
    /// </summary>
    [JsonPropertyName("append_ocr_text")]
    public bool AppendOcrText { get; init; } = false;


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

    public static ImageExtractionConfig Default()
    {
        var nativeResult = NativeMethods.ImageExtractionConfigDefault();
        var jsonPtr = NativeMethods.ImageExtractionConfigToJson(nativeResult);
        var json = global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(jsonPtr);
        NativeMethods.FreeString(jsonPtr);
        NativeMethods.ImageExtractionConfigFree(nativeResult);
        return JsonSerializer.Deserialize<ImageExtractionConfig>(json ?? "null", JsonOptions)!;
    }
}
