// 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 dev.kreuzberg;

import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.jspecify.annotations.Nullable;

/**
 * Format-specific metadata (discriminated union).
 *
 * Only one format type can exist per extraction result. This provides
 * type-safe, clean metadata without nested optionals.
 */
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
@JsonDeserialize(using = FormatMetadataDeserializer.class)
@JsonSerialize(using = FormatMetadataSerializer.class)
public sealed interface FormatMetadata {

    record Pdf(PdfMetadata value) implements FormatMetadata { }

    record Docx(DocxMetadata value) implements FormatMetadata { }

    record Excel(ExcelMetadata value) implements FormatMetadata { }

    record Email(EmailMetadata value) implements FormatMetadata { }

    record Pptx(PptxMetadata value) implements FormatMetadata { }

    record Archive(ArchiveMetadata value) implements FormatMetadata { }

    record Image(ImageMetadata value) implements FormatMetadata { }

    record Xml(XmlMetadata value) implements FormatMetadata { }

    record Text(TextMetadata value) implements FormatMetadata { }

    record Html(HtmlMetadata value) implements FormatMetadata { }

    record Ocr(OcrMetadata value) implements FormatMetadata { }

    record Csv(CsvMetadata value) implements FormatMetadata { }

    record Bibtex(BibtexMetadata value) implements FormatMetadata { }

    record Citation(CitationMetadata value) implements FormatMetadata { }

    record FictionBook(FictionBookMetadata value) implements FormatMetadata { }

    record Dbf(DbfMetadata value) implements FormatMetadata { }

    record Jats(JatsMetadata value) implements FormatMetadata { }

    record Epub(EpubMetadata value) implements FormatMetadata { }

    record Pst(PstMetadata value) implements FormatMetadata { }

    record Code(String value) implements FormatMetadata { }

    /** Returns the Pdf data if this is a Pdf variant, otherwise null. */
    default @Nullable PdfMetadata pdf() {
        return this instanceof Pdf e ? e.value() : null;
    }

    /** Returns the Docx data if this is a Docx variant, otherwise null. */
    default @Nullable DocxMetadata docx() {
        return this instanceof Docx e ? e.value() : null;
    }

    /** Returns the Excel data if this is a Excel variant, otherwise null. */
    default @Nullable ExcelMetadata excel() {
        return this instanceof Excel e ? e.value() : null;
    }

    /** Returns the Email data if this is a Email variant, otherwise null. */
    default @Nullable EmailMetadata email() {
        return this instanceof Email e ? e.value() : null;
    }

    /** Returns the Pptx data if this is a Pptx variant, otherwise null. */
    default @Nullable PptxMetadata pptx() {
        return this instanceof Pptx e ? e.value() : null;
    }

    /** Returns the Archive data if this is a Archive variant, otherwise null. */
    default @Nullable ArchiveMetadata archive() {
        return this instanceof Archive e ? e.value() : null;
    }

    /** Returns the Image data if this is a Image variant, otherwise null. */
    default @Nullable ImageMetadata image() {
        return this instanceof Image e ? e.value() : null;
    }

    /** Returns the Xml data if this is a Xml variant, otherwise null. */
    default @Nullable XmlMetadata xml() {
        return this instanceof Xml e ? e.value() : null;
    }

    /** Returns the Text data if this is a Text variant, otherwise null. */
    default @Nullable TextMetadata text() {
        return this instanceof Text e ? e.value() : null;
    }

    /** Returns the Html data if this is a Html variant, otherwise null. */
    default @Nullable HtmlMetadata html() {
        return this instanceof Html e ? e.value() : null;
    }

    /** Returns the Ocr data if this is a Ocr variant, otherwise null. */
    default @Nullable OcrMetadata ocr() {
        return this instanceof Ocr e ? e.value() : null;
    }

    /** Returns the Csv data if this is a Csv variant, otherwise null. */
    default @Nullable CsvMetadata csv() {
        return this instanceof Csv e ? e.value() : null;
    }

    /** Returns the Bibtex data if this is a Bibtex variant, otherwise null. */
    default @Nullable BibtexMetadata bibtex() {
        return this instanceof Bibtex e ? e.value() : null;
    }

    /** Returns the Citation data if this is a Citation variant, otherwise null. */
    default @Nullable CitationMetadata citation() {
        return this instanceof Citation e ? e.value() : null;
    }

    /** Returns the FictionBook data if this is a FictionBook variant, otherwise null. */
    default @Nullable FictionBookMetadata fictionBook() {
        return this instanceof FictionBook e ? e.value() : null;
    }

    /** Returns the Dbf data if this is a Dbf variant, otherwise null. */
    default @Nullable DbfMetadata dbf() {
        return this instanceof Dbf e ? e.value() : null;
    }

    /** Returns the Jats data if this is a Jats variant, otherwise null. */
    default @Nullable JatsMetadata jats() {
        return this instanceof Jats e ? e.value() : null;
    }

    /** Returns the Epub data if this is a Epub variant, otherwise null. */
    default @Nullable EpubMetadata epub() {
        return this instanceof Epub e ? e.value() : null;
    }

    /** Returns the Pst data if this is a Pst variant, otherwise null. */
    default @Nullable PstMetadata pst() {
        return this instanceof Pst e ? e.value() : null;
    }

    /** Returns the Code data if this is a Code variant, otherwise null. */
    default @Nullable String code() {
        return this instanceof Code e ? e.value() : null;
    }

}

// Custom deserializer for sealed interface with unwrapped variants
class FormatMetadataDeserializer extends StdDeserializer<FormatMetadata> {
    FormatMetadataDeserializer() {
        super(FormatMetadata.class);
    }

    @Override
    public FormatMetadata deserialize(JsonParser parser, DeserializationContext ctx)
            throws java.io.IOException {
        ObjectNode node = parser.getCodec().readTree(parser);
        com.fasterxml.jackson.databind.JsonNode tagNode = node.get("format_type");
        if (tagNode == null || tagNode.isNull()) {
            throw new com.fasterxml.jackson.databind.JsonMappingException(
                parser, "Missing discriminator field: format_type");
        }
        String tagValue = tagNode.asText();
        node.remove("format_type");

        return switch (tagValue) {
            case "pdf" -> new FormatMetadata.Pdf(ctx.readTreeAsValue(node, PdfMetadata.class));
            case "docx" -> new FormatMetadata.Docx(ctx.readTreeAsValue(node, DocxMetadata.class));
            case "excel" -> new FormatMetadata.Excel(ctx.readTreeAsValue(node, ExcelMetadata.class));
            case "email" -> new FormatMetadata.Email(ctx.readTreeAsValue(node, EmailMetadata.class));
            case "pptx" -> new FormatMetadata.Pptx(ctx.readTreeAsValue(node, PptxMetadata.class));
            case "archive" -> new FormatMetadata.Archive(ctx.readTreeAsValue(node, ArchiveMetadata.class));
            case "image" -> new FormatMetadata.Image(ctx.readTreeAsValue(node, ImageMetadata.class));
            case "xml" -> new FormatMetadata.Xml(ctx.readTreeAsValue(node, XmlMetadata.class));
            case "text" -> new FormatMetadata.Text(ctx.readTreeAsValue(node, TextMetadata.class));
            case "html" -> new FormatMetadata.Html(ctx.readTreeAsValue(node, HtmlMetadata.class));
            case "ocr" -> new FormatMetadata.Ocr(ctx.readTreeAsValue(node, OcrMetadata.class));
            case "csv" -> new FormatMetadata.Csv(ctx.readTreeAsValue(node, CsvMetadata.class));
            case "bibtex" -> new FormatMetadata.Bibtex(ctx.readTreeAsValue(node, BibtexMetadata.class));
            case "citation" -> new FormatMetadata.Citation(ctx.readTreeAsValue(node, CitationMetadata.class));
            case "fiction_book" -> new FormatMetadata.FictionBook(ctx.readTreeAsValue(node, FictionBookMetadata.class));
            case "dbf" -> new FormatMetadata.Dbf(ctx.readTreeAsValue(node, DbfMetadata.class));
            case "jats" -> new FormatMetadata.Jats(ctx.readTreeAsValue(node, JatsMetadata.class));
            case "epub" -> new FormatMetadata.Epub(ctx.readTreeAsValue(node, EpubMetadata.class));
            case "pst" -> new FormatMetadata.Pst(ctx.readTreeAsValue(node, PstMetadata.class));
            case "code" -> new FormatMetadata.Code(node.toString());
            default -> throw new com.fasterxml.jackson.databind.JsonMappingException(
                parser, "Unknown FormatMetadata discriminator: " + tagValue);
        };
    }
}

// Custom serializer for sealed interface with unwrapped variants — emits
// the discriminator tag alongside the inner record's fields (flat object).
class FormatMetadataSerializer extends StdSerializer<FormatMetadata> {
    private static final com.fasterxml.jackson.databind.ObjectMapper MAPPER =
        new com.fasterxml.jackson.databind.ObjectMapper()
            .registerModule(new com.fasterxml.jackson.datatype.jdk8.Jdk8Module())
            .setPropertyNamingStrategy(com.fasterxml.jackson.databind.PropertyNamingStrategies.SNAKE_CASE)
            .setSerializationInclusion(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL);

    FormatMetadataSerializer() {
        super(FormatMetadata.class);
    }

    @Override
    public void serialize(FormatMetadata value, JsonGenerator gen, SerializerProvider provider)
            throws java.io.IOException {
        String tag;
        Object inner;if (value instanceof FormatMetadata.Pdf v) {
            tag = "pdf";            inner = v.value();        }else if (value instanceof FormatMetadata.Docx v) {
            tag = "docx";            inner = v.value();        }else if (value instanceof FormatMetadata.Excel v) {
            tag = "excel";            inner = v.value();        }else if (value instanceof FormatMetadata.Email v) {
            tag = "email";            inner = v.value();        }else if (value instanceof FormatMetadata.Pptx v) {
            tag = "pptx";            inner = v.value();        }else if (value instanceof FormatMetadata.Archive v) {
            tag = "archive";            inner = v.value();        }else if (value instanceof FormatMetadata.Image v) {
            tag = "image";            inner = v.value();        }else if (value instanceof FormatMetadata.Xml v) {
            tag = "xml";            inner = v.value();        }else if (value instanceof FormatMetadata.Text v) {
            tag = "text";            inner = v.value();        }else if (value instanceof FormatMetadata.Html v) {
            tag = "html";            inner = v.value();        }else if (value instanceof FormatMetadata.Ocr v) {
            tag = "ocr";            inner = v.value();        }else if (value instanceof FormatMetadata.Csv v) {
            tag = "csv";            inner = v.value();        }else if (value instanceof FormatMetadata.Bibtex v) {
            tag = "bibtex";            inner = v.value();        }else if (value instanceof FormatMetadata.Citation v) {
            tag = "citation";            inner = v.value();        }else if (value instanceof FormatMetadata.FictionBook v) {
            tag = "fiction_book";            inner = v.value();        }else if (value instanceof FormatMetadata.Dbf v) {
            tag = "dbf";            inner = v.value();        }else if (value instanceof FormatMetadata.Jats v) {
            tag = "jats";            inner = v.value();        }else if (value instanceof FormatMetadata.Epub v) {
            tag = "epub";            inner = v.value();        }else if (value instanceof FormatMetadata.Pst v) {
            tag = "pst";            inner = v.value();        }else if (value instanceof FormatMetadata.Code v) {
            tag = "code";            inner = v.value();        }        else {
            throw new com.fasterxml.jackson.databind.JsonMappingException(gen,
                "Unknown FormatMetadata variant: " + value.getClass().getName());
        }

        gen.writeStartObject();
        gen.writeStringField("format_type", tag);
        if (inner != null) {
            com.fasterxml.jackson.databind.JsonNode tree = MAPPER.valueToTree(inner);
            if (tree.isObject()) {
                java.util.Iterator<java.util.Map.Entry<String, com.fasterxml.jackson.databind.JsonNode>> it =
                    tree.fields();
                while (it.hasNext()) {
                    java.util.Map.Entry<String, com.fasterxml.jackson.databind.JsonNode> e = it.next();
                    gen.writeFieldName(e.getKey());
                    gen.writeTree(e.getValue());
                }
            }
        }
        gen.writeEndObject();
    }
}
