// 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
const std = @import("std");
const testing = std.testing;
const kreuzberg = @import("kreuzberg");

// Suppress C++ global destructor aborts that break zig's --listen=- IPC
extern "c" fn signal(sig: i32, handler: usize) usize;
var _abort_handler_installed: bool = false;
fn suppress_abort() void {
    if (!_abort_handler_installed) {
        // SIGABRT = 6 on POSIX; SIG_IGN = 1
        _ = signal(6, 1);
        _abort_handler_installed = true;
    }
}

// E2e tests for category: contract

test "api_batch_bytes_async" {
    // Tests async batch bytes extraction API (batch_extract_bytes)
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("pdf/fake_memo.pdf", null, "{}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/pdf", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 10);
    try testing.expect(
        std.mem.indexOf(u8, result.object.get("content").?.string, "May 5, 2023") != null or
        std.mem.indexOf(u8, result.object.get("content").?.string, "Mallori") != null
    );
}

test "api_batch_bytes_with_configs_async" {
    // Tests async batch bytes extraction with per-file configs (batch_extract_bytes with file_configs parameter)
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("pdf/fake_memo.pdf", null, "{\"output_format\":\"markdown\"}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/pdf", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 10);
    // skipped: field 'metadata.output_format' not available on result type
}

test "api_batch_file_async" {
    // Tests async batch file extraction API (batch_extract_file)
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("pdf/fake_memo.pdf", null, "{}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/pdf", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 10);
    try testing.expect(
        std.mem.indexOf(u8, result.object.get("content").?.string, "May 5, 2023") != null or
        std.mem.indexOf(u8, result.object.get("content").?.string, "Mallori") != null
    );
}

test "api_batch_file_with_configs_async" {
    // Tests async batch file extraction with per-file configs (batch_extract_files with file_configs parameter)
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("pdf/fake_memo.pdf", null, "{\"output_format\":\"markdown\"}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/pdf", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 10);
    // skipped: field 'metadata.output_format' not available on result type
}

test "api_extract_bytes_async" {
    // Tests async bytes extraction API (extract_bytes)
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("pdf/fake_memo.pdf", null, "{}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/pdf", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 10);
    try testing.expect(
        std.mem.indexOf(u8, result.object.get("content").?.string, "May 5, 2023") != null or
        std.mem.indexOf(u8, result.object.get("content").?.string, "Mallori") != null
    );
}

test "api_extract_file_async" {
    // Tests async file extraction API (extract_file)
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("pdf/fake_memo.pdf", null, "{}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/pdf", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 10);
    try testing.expect(
        std.mem.indexOf(u8, result.object.get("content").?.string, "May 5, 2023") != null or
        std.mem.indexOf(u8, result.object.get("content").?.string, "Mallori") != null
    );
}

test "config_chunking_prepend_heading_context" {
    // Tests markdown chunker prepends heading hierarchy to chunk content
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("markdown/extraction_test.md", null, "{\"chunking\":{\"chunker_type\":\"markdown\",\"max_chars\":300,\"max_overlap\":50,\"prepend_heading_context\":true}}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expect(result.object.get("content").?.string.len >= 10);
    // skipped: field 'chunks' not available on result type
    {
        const _chunks_opt = result.object.get("chunks");
        var _all: bool = true;
        if (_chunks_opt) |_chunks_val| {
            if (_chunks_val == .array) {
                if (_chunks_val.array.items.len == 0) _all = false;
                for (_chunks_val.array.items) |c| {
                    if (c != .object) { _all = false; break; }
                    const _v = c.object.get("content");
                    if (_v == null or _v.? != .string or _v.?.string.len == 0) { _all = false; break; }
                }
            } else { _all = false; }
        } else { _all = false; }
        try testing.expect(_all);
    }
    // skipped: synthetic field 'chunks_have_heading_context' not derivable from JSON value alone
    // skipped: synthetic field 'first_chunk_starts_with_heading' not derivable from JSON value alone
}

test "config_document_structure_with_headings" {
    // Tests document structure with DOCX heading-driven nesting
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("docx/fake.docx", null, "{\"include_document_structure\":true}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/vnd.openxmlformats-officedocument.wordprocessingml.document", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    // skipped: field 'document' not available on result type
    // skipped: field 'document.nodes' not available on result type
}

test "config_element_types" {
    // Tests element-based result format with element type assertions on DOCX
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("docx/unit_test_headers.docx", null, "{\"result_format\":\"element_based\"}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expect(
        std.mem.indexOf(u8, result.object.get("mime_type").?.string, "application/vnd.openxmlformats-officedocument.wordprocessingml.document") != null
    );
    // skipped: field 'elements' not available on result type
}

test "config_extraction_timeout" {
    // Tests that extraction_timeout_secs config field is accepted and does not affect fast extractions
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("pdf/fake_memo.pdf", null, "{\"extraction_timeout_secs\":300}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/pdf", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 10);
}

test "config_keywords" {
    // Tests keyword extraction via YAKE algorithm
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("pdf/fake_memo.pdf", null, "{\"keywords\":{\"algorithm\":\"yake\",\"max_keywords\":10}}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/pdf", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 10);
    // skipped: field 'keywords' not available on JSON-struct ExtractionResult
    // skipped: field 'keywords' not available on JSON-struct ExtractionResult
}

test "config_pages" {
    // Tests page extraction and page marker configuration
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("pdf/fake_memo.pdf", null, "{\"pages\":{\"extract_pages\":true,\"insert_page_markers\":true}}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/pdf", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 10);
    try testing.expect(
        std.mem.indexOf(u8, result.object.get("content").?.string, "PAGE") != null
    );
}

test "config_quality_enabled" {
    // Tests quality scoring produces a score value in [0.0, 1.0]
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("pdf/fake_memo.pdf", null, "{\"enable_quality_processing\":true}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/pdf", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 10);
    // skipped: field 'quality_score' not available on result type
    // skipped: field 'quality_score' not available on result type
    // skipped: field 'quality_score' not available on result type
}

test "config_security_limits" {
    // Tests archive extraction with custom security limits
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("archives/documents.zip", null, "{\"security_limits\":{\"max_archive_size\":104857600,\"max_compression_ratio\":50,\"max_files_in_archive\":100}}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expect(
        std.mem.indexOf(u8, result.object.get("mime_type").?.string, "application/zip") != null or
        std.mem.indexOf(u8, result.object.get("mime_type").?.string, "application/x-zip-compressed") != null
    );
    try testing.expect(result.object.get("content").?.string.len >= 10);
}

test "config_tree_sitter" {
    // Tests tree-sitter configuration round-trip
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("code/hello.py", null, "{\"tree_sitter\":{\"groups\":[\"web\"],\"languages\":[\"python\",\"rust\"],\"process\":{\"comments\":false,\"diagnostics\":false,\"docstrings\":false,\"exports\":true,\"imports\":true,\"structure\":true,\"symbols\":false}}}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("text/x-source-code", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 5);
}

test "output_format_bytes_markdown" {
    // Tests markdown output format via bytes extraction API
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const content_bytes = try std.Io.Dir.cwd().readFileAlloc(std.testing.io, "pdf/fake_memo.pdf", std.heap.c_allocator, .unlimited);
    defer std.heap.c_allocator.free(content_bytes);
    const _result_json = try kreuzberg.extract_bytes_sync(content_bytes, "application/pdf", "{\"output_format\":\"markdown\"}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/pdf", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 10);
    // skipped: field 'metadata.output_format' not available on result type
}

test "output_format_markdown" {
    // Tests Markdown output format
    suppress_abort();
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const _result_json = try kreuzberg.extract_file_sync("pdf/fake_memo.pdf", null, "{\"output_format\":\"markdown\"}");
    defer std.heap.c_allocator.free(_result_json);
    var _parsed = try std.json.parseFromSlice(std.json.Value, allocator, _result_json, .{});
    defer _parsed.deinit();
    const result = &_parsed.value;
    try testing.expectEqualStrings("application/pdf", std.mem.trim(u8, result.object.get("mime_type").?.string, " \n\r\t"));
    try testing.expect(result.object.get("content").?.string.len >= 10);
    // skipped: field 'metadata.output_format' not available on result type
}
