// 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.IO;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Kreuzberg;

/// <summary>
/// Types of inline text annotations.
/// </summary>
    [JsonConverter(typeof(AnnotationKindJsonConverter))]
public abstract record AnnotationKind
{
    public sealed record Bold() : AnnotationKind;

    public sealed record Italic() : AnnotationKind;

    public sealed record Underline() : AnnotationKind;

    public sealed record Strikethrough() : AnnotationKind;

    public sealed record Code() : AnnotationKind;

    public sealed record Subscript() : AnnotationKind;

    public sealed record Superscript() : AnnotationKind;

    public sealed record Link(
        [property: JsonPropertyName("url")] string Url,
        [property: JsonPropertyName("title")] string? Title
    ) : AnnotationKind;

    /// <summary>
    /// Highlighted text (PDF highlights, HTML `&lt;mark&gt;`).
    /// </summary>
    public sealed record Highlight() : AnnotationKind;

    /// <summary>
    /// Text color (CSS-compatible value, e.g. "#ff0000", "red").
    /// </summary>
    public sealed record Color(
        [property: JsonPropertyName("value")] string Value
    ) : AnnotationKind;

    /// <summary>
    /// Font size with units (e.g. "12pt", "1.2em", "16px").
    /// </summary>
    public sealed record FontSize(
        [property: JsonPropertyName("value")] string Value
    ) : AnnotationKind;

    /// <summary>
    /// Extensible annotation for format-specific styling.
    /// </summary>
    public sealed record Custom(
        [property: JsonPropertyName("name")] string Name,
        [property: JsonPropertyName("value")] string? Value
    ) : AnnotationKind;

}

/// <summary>
/// Custom converter for AnnotationKind sealed union with flattened variant fields.
/// </summary>
/// <remarks>
/// Handles JSON objects with a discriminator field (annotation_type) and variant-specific
/// fields at the same level. System.Text.Json's [JsonPolymorphic] cannot handle
/// this layout, so we manually deserialize here.
/// </remarks>
public sealed class AnnotationKindJsonConverter : JsonConverter<AnnotationKind>
{
    public override AnnotationKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartObject)
        {
            throw new JsonException($"Expected JSON object, got {reader.TokenType}");
        }

        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;

        if (!root.TryGetProperty("annotation_type", out var tagElement))
        {
            throw new JsonException($"Missing discriminator field: annotation_type");
        }

        var tagValue = tagElement.GetString();
        if (tagValue == null)
        {
            throw new JsonException("Discriminator field is null");
        }

        // Tuple-variant records (`Variant(InnerStruct value)`) expect a single
        // "Value" field holding the inner struct's JSON, so wrap the remaining
        // fields under "Value". Struct-variant records (`Variant { field1,
        // field2 }`) have positional record components annotated with
        // [JsonPropertyName(...)] for each named field, so pass the remaining
        // fields through directly without the wrap.
        using var ms = new MemoryStream();
        using var writer = new Utf8JsonWriter(ms);
        writer.WriteStartObject();
        foreach (var prop in root.EnumerateObject())
        {
            if (prop.Name != "annotation_type")
            {
                writer.WritePropertyName(prop.Name);
                prop.Value.WriteTo(writer);
            }
        }
        writer.WriteEndObject();
        writer.Flush();
        ms.Position = 0;
        var flatJson = ms.ToArray();

        using var msWrapped = new MemoryStream();
        using var writerWrapped = new Utf8JsonWriter(msWrapped);
        writerWrapped.WriteStartObject();
        writerWrapped.WritePropertyName("Value");
        writerWrapped.WriteStartObject();
        foreach (var prop in root.EnumerateObject())
        {
            if (prop.Name != "annotation_type")
            {
                writerWrapped.WritePropertyName(prop.Name);
                prop.Value.WriteTo(writerWrapped);
            }
        }
        writerWrapped.WriteEndObject();
        writerWrapped.WriteEndObject();
        writerWrapped.Flush();
        msWrapped.Position = 0;
        var wrappedJson = msWrapped.ToArray();

        return tagValue switch
        {            "bold" => new AnnotationKind.Bold(),            "italic" => new AnnotationKind.Italic(),            "underline" => new AnnotationKind.Underline(),            "strikethrough" => new AnnotationKind.Strikethrough(),            "code" => new AnnotationKind.Code(),            "subscript" => new AnnotationKind.Subscript(),            "superscript" => new AnnotationKind.Superscript(),            "link" => JsonSerializer.Deserialize<AnnotationKind.Link>(flatJson, options) ?? throw new JsonException("Failed to deserialize variant"),            "highlight" => new AnnotationKind.Highlight(),            "color" => JsonSerializer.Deserialize<AnnotationKind.Color>(flatJson, options) ?? throw new JsonException("Failed to deserialize variant"),            "font_size" => JsonSerializer.Deserialize<AnnotationKind.FontSize>(flatJson, options) ?? throw new JsonException("Failed to deserialize variant"),            "custom" => JsonSerializer.Deserialize<AnnotationKind.Custom>(flatJson, options) ?? throw new JsonException("Failed to deserialize variant"),            _ => throw new JsonException($"Unknown AnnotationKind discriminator: {tagValue}")
        };
    }

    public override void Write(Utf8JsonWriter writer, AnnotationKind value, JsonSerializerOptions options)
    {
        // Emit the discriminator tag plus the inner variant's fields flattened at
        // the same level — mirrors the Java sealed-union serializer pattern. Turn
        // `Message.User(UserMessage value)` into `{"annotation_type":"user","content":...}`
        // not `{"value":{...}}`. Without this, sending a chat request to FFI fails
        // with "missing field annotation_type" inside Rust serde.
        string tag;
        object? inner;
        switch (value)
        {            case AnnotationKind.Bold _:
                tag = "bold";
                inner = null;
                break;            case AnnotationKind.Italic _:
                tag = "italic";
                inner = null;
                break;            case AnnotationKind.Underline _:
                tag = "underline";
                inner = null;
                break;            case AnnotationKind.Strikethrough _:
                tag = "strikethrough";
                inner = null;
                break;            case AnnotationKind.Code _:
                tag = "code";
                inner = null;
                break;            case AnnotationKind.Subscript _:
                tag = "subscript";
                inner = null;
                break;            case AnnotationKind.Superscript _:
                tag = "superscript";
                inner = null;
                break;            case AnnotationKind.Link v_link:
                tag = "link";                inner = v_link;                break;            case AnnotationKind.Highlight _:
                tag = "highlight";
                inner = null;
                break;            case AnnotationKind.Color v_color:
                tag = "color";                inner = v_color;                break;            case AnnotationKind.FontSize v_fontsize:
                tag = "font_size";                inner = v_fontsize;                break;            case AnnotationKind.Custom v_custom:
                tag = "custom";                inner = v_custom;                break;            default:
                throw new JsonException($"Unknown AnnotationKind variant: {value.GetType().Name}");
        }

        writer.WriteStartObject();
        writer.WriteString("annotation_type", tag);
        if (inner != null)
        {
            using var doc = JsonSerializer.SerializeToDocument(inner, inner.GetType(), options);
            if (doc.RootElement.ValueKind == JsonValueKind.Object)
            {
                foreach (var prop in doc.RootElement.EnumerateObject())
                {
                    writer.WritePropertyName(prop.Name);
                    prop.Value.WriteTo(writer);
                }
            }
        }
        writer.WriteEndObject();
    }
}
