// 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>
/// Content for a single page/slide.
///
/// When page extraction is enabled, documents are split into per-page content
/// with associated tables and images mapped to each page.
///
/// # Performance
///
/// Uses Arc-wrapped tables and images for memory efficiency:
/// - `Vec&lt;Arc&lt;Table&gt;&gt;` enables zero-copy sharing of table data
/// - `Vec&lt;Arc&lt;ExtractedImage&gt;&gt;` enables zero-copy sharing of image data
/// - Maintains exact JSON compatibility via custom Serialize/Deserialize
///
/// This reduces memory overhead for documents with shared tables/images
/// by avoiding redundant copies during serialization.
/// </summary>
public sealed record PageContent
{
    /// <summary>
    /// Page number (1-indexed)
    /// </summary>
    [JsonPropertyName("page_number")]
    public uint PageNumber { get; init; } = 0;

    /// <summary>
    /// Text content for this page
    /// </summary>
    [JsonPropertyName("content")]
    public required string Content { get; init; }

    /// <summary>
    /// Tables found on this page (uses Arc for memory efficiency)
    ///
    /// Serializes as Table[] for JSON compatibility while maintaining
    /// Arc semantics in-memory for zero-copy sharing.
    /// </summary>
    [JsonPropertyName("tables")]
    public List<Table> Tables { get; init; } = [];

    /// <summary>
    /// Indices into `ExtractionResult.images` for images found on this page.
    ///
    /// Each value is a zero-based index into the top-level `images` collection.
    /// Only populated when `extract_images = true` in the extraction config.
    /// </summary>
    [JsonPropertyName("image_indices")]
    public List<uint> ImageIndices { get; init; } = [];

    /// <summary>
    /// Hierarchy information for the page (when hierarchy extraction is enabled)
    ///
    /// Contains text hierarchy levels (H1-H6) extracted from the page content.
    /// </summary>
    [JsonPropertyName("hierarchy")]
    public PageHierarchy? Hierarchy { get; init; } = null;

    /// <summary>
    /// Whether this page is blank (no meaningful text content)
    ///
    /// Determined during extraction based on text content analysis.
    /// A page is blank if it has fewer than 3 non-whitespace characters
    /// and contains no tables or images.
    /// </summary>
    [JsonPropertyName("is_blank")]
    public bool? IsBlank { get; init; } = null;

    /// <summary>
    /// Layout detection regions for this page (when layout detection is enabled).
    ///
    /// Contains detected layout regions with class, confidence, bounding box,
    /// and area fraction. Only populated when layout detection is configured.
    /// </summary>
    [JsonPropertyName("layout_regions")]
    public List<LayoutRegion>? LayoutRegions { get; init; } = null;

    /// <summary>
    /// Speaker notes for this slide (PPTX only).
    ///
    /// Contains the text from the slide's notes pane (`ppt/notesSlides/notesSlide{N}.xml`).
    /// Only populated when the source is a PPTX file and notes are present.
    /// </summary>
    [JsonPropertyName("speaker_notes")]
    public string? SpeakerNotes { get; init; } = null;

    /// <summary>
    /// Section name this slide belongs to (PPTX only).
    ///
    /// PowerPoint sections group slides into logical chapters (`&lt;p:sectionLst&gt;` in
    /// `ppt/presentation.xml`). Only populated when the source is a PPTX file and
    /// the slide belongs to a named section.
    /// </summary>
    [JsonPropertyName("section_name")]
    public string? SectionName { get; init; } = null;

    /// <summary>
    /// Sheet name for this page (XLSX/ODS only).
    ///
    /// Each spreadsheet sheet maps to one `PageContent` entry. This field carries the
    /// sheet's display name as it appears in the workbook. `None` for all non-spreadsheet
    /// formats and for sheets with an empty name.
    /// </summary>
    [JsonPropertyName("sheet_name")]
    public string? SheetName { get; init; } = null;


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