/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include <arrow/c/bridge.h>

#include <cassert>
#include <ctime>

#include "ffi_converter.hpp"
#include "fluss.hpp"
#include "lib.rs.h"
#include "rust/cxx.h"
#include "type_lowering.hpp"
// todo:  bindings/cpp/BUILD.bazel still doesn't declare Arrow include/link dependencies.
// In environments where Bazel does not already have Arrow available, this will fail at compile/link
// time.
#include <arrow/record_batch.h>
#include <arrow/type.h>

namespace fluss {

static constexpr int kSecondsPerDay = 24 * 60 * 60;

static std::time_t timegm_utc(std::tm* tm) {
#if defined(_WIN32)
    return _mkgmtime(tm);
#else
    return ::timegm(tm);
#endif
}

static std::tm gmtime_utc(std::time_t epoch_seconds) {
    std::tm tm{};
#if defined(_WIN32)
    gmtime_s(&tm, &epoch_seconds);
#else
    ::gmtime_r(&epoch_seconds, &tm);
#endif
    return tm;
}

Date Date::FromYMD(int year, int month, int day) {
    std::tm tm{};
    tm.tm_year = year - 1900;
    tm.tm_mon = month - 1;
    tm.tm_mday = day;
    std::time_t epoch_seconds = timegm_utc(&tm);
    return {static_cast<int32_t>(epoch_seconds / kSecondsPerDay)};
}

int Date::Year() const {
    std::time_t epoch_seconds = static_cast<std::time_t>(days_since_epoch) * kSecondsPerDay;
    std::tm tm = gmtime_utc(epoch_seconds);
    return tm.tm_year + 1900;
}

int Date::Month() const {
    std::time_t epoch_seconds = static_cast<std::time_t>(days_since_epoch) * kSecondsPerDay;
    std::tm tm = gmtime_utc(epoch_seconds);
    return tm.tm_mon + 1;
}

int Date::Day() const {
    std::time_t epoch_seconds = static_cast<std::time_t>(days_since_epoch) * kSecondsPerDay;
    std::tm tm = gmtime_utc(epoch_seconds);
    return tm.tm_mday;
}

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define CHECK_INNER(name)                                                                 \
    do {                                                                                  \
        if (!inner_) throw std::logic_error(name ": not available (moved-from or null)"); \
    } while (0)

namespace {

ffi::ArrayWriterInner* make_array_writer_arrow(size_t size,
                                               std::shared_ptr<arrow::DataType> element,
                                               bool nullable) {
    auto schema = arrow::schema({arrow::field("element", std::move(element), nullable)});
    return ffi::new_array_writer_arrow(size, detail::export_arrow_schema(*schema)).into_raw();
}

ffi::MapWriterInner* make_map_writer_arrow(size_t capacity, std::shared_ptr<arrow::DataType> key,
                                           std::shared_ptr<arrow::DataType> value,
                                           bool value_nullable) {
    auto schema = arrow::schema({
        arrow::field("key", std::move(key), /*nullable=*/false),
        arrow::field("value", std::move(value), value_nullable),
    });
    return ffi::new_map_writer_arrow(capacity, detail::export_arrow_schema(*schema)).into_raw();
}

}  // namespace

// ============================================================================
// ArrayWriter — builder for array values backed by Rust ArrayWriterInner
// ============================================================================

ArrayWriter::ArrayWriter(size_t size, DataType element_type) : element_type_(std::move(element_type)) {
    if (detail::is_compound(element_type_)) {
        inner_ = make_array_writer_arrow(size, detail::to_arrow_type(element_type_),
                                         element_type_.nullable());
        return;
    }

    auto flat = utils::flatten_array_type(element_type_);
    int32_t leaf_type_id = flat.nesting > 0 ? flat.leaf_type : static_cast<int32_t>(element_type_.id());
    uint32_t leaf_precision = static_cast<uint32_t>(flat.nesting > 0 ? flat.leaf_precision
                                                                      : element_type_.precision());
    uint32_t leaf_scale = static_cast<uint32_t>(flat.nesting > 0 ? flat.leaf_scale : element_type_.scale());
    uint32_t array_nesting = static_cast<uint32_t>(flat.nesting);

    auto box = ffi::new_array_writer(size, leaf_type_id, leaf_precision, leaf_scale, array_nesting);
    inner_ = box.into_raw();
}

ArrayWriter::ArrayWriter(size_t size, std::shared_ptr<arrow::DataType> element_type)
    : element_type_(DataType::Int()) {  // placeholder; Rust holds the real element type
    inner_ = make_array_writer_arrow(size, std::move(element_type), /*nullable=*/true);
}

ArrayWriter::~ArrayWriter() noexcept { Destroy(); }

void ArrayWriter::Destroy() noexcept {
    if (inner_) {
        rust::Box<ffi::ArrayWriterInner>::from_raw(inner_);
        inner_ = nullptr;
    }
}

ArrayWriter::ArrayWriter(ArrayWriter&& other) noexcept
    : inner_(other.inner_), element_type_(std::move(other.element_type_)) {
    other.inner_ = nullptr;
}

ArrayWriter& ArrayWriter::operator=(ArrayWriter&& other) noexcept {
    if (this != &other) {
        Destroy();
        inner_ = other.inner_;
        element_type_ = std::move(other.element_type_);
        other.inner_ = nullptr;
    }
    return *this;
}

bool ArrayWriter::Available() const { return inner_ != nullptr; }

size_t ArrayWriter::Size() const noexcept {
    assert(inner_ && "ArrayWriter::Size called on moved-from instance");
    return inner_->aw_size();
}

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define CHECK_AW(name)                                                                    \
    do {                                                                                  \
        if (!inner_) throw std::logic_error(name ": not available (moved-from or null)"); \
    } while (0)

void ArrayWriter::SetNull(size_t idx) { CHECK_AW("ArrayWriter"); inner_->aw_set_null(idx); }
void ArrayWriter::SetBool(size_t idx, bool v) { CHECK_AW("ArrayWriter"); inner_->aw_set_bool(idx, v); }
void ArrayWriter::SetInt32(size_t idx, int32_t v) { CHECK_AW("ArrayWriter"); inner_->aw_set_i32(idx, v); }
void ArrayWriter::SetInt64(size_t idx, int64_t v) { CHECK_AW("ArrayWriter"); inner_->aw_set_i64(idx, v); }
void ArrayWriter::SetFloat32(size_t idx, float v) { CHECK_AW("ArrayWriter"); inner_->aw_set_f32(idx, v); }
void ArrayWriter::SetFloat64(size_t idx, double v) { CHECK_AW("ArrayWriter"); inner_->aw_set_f64(idx, v); }

void ArrayWriter::SetString(size_t idx, const std::string& v) {
    CHECK_AW("ArrayWriter");
    inner_->aw_set_str(idx, v);
}

void ArrayWriter::SetBytes(size_t idx, const std::vector<uint8_t>& v) {
    CHECK_AW("ArrayWriter");
    inner_->aw_set_bytes(idx, rust::Slice<const uint8_t>(v.data(), v.size()));
}

void ArrayWriter::SetDate(size_t idx, fluss::Date d) {
    CHECK_AW("ArrayWriter");
    inner_->aw_set_date(idx, d.days_since_epoch);
}

void ArrayWriter::SetTime(size_t idx, fluss::Time t) {
    CHECK_AW("ArrayWriter");
    inner_->aw_set_time(idx, t.millis_since_midnight);
}

void ArrayWriter::SetTimestampNtz(size_t idx, fluss::Timestamp ts) {
    CHECK_AW("ArrayWriter");
    inner_->aw_set_ts_ntz(idx, ts.epoch_millis, ts.nano_of_millisecond);
}

void ArrayWriter::SetTimestampLtz(size_t idx, fluss::Timestamp ts) {
    CHECK_AW("ArrayWriter");
    inner_->aw_set_ts_ltz(idx, ts.epoch_millis, ts.nano_of_millisecond);
}

void ArrayWriter::SetDecimal(size_t idx, const std::string& value) {
    CHECK_AW("ArrayWriter");
    inner_->aw_set_decimal_str(idx, value);
}

void ArrayWriter::SetArray(size_t idx, ArrayWriter&& nested) {
    CHECK_AW("ArrayWriter");
    if (!nested.inner_) {
        throw std::logic_error("ArrayWriter::SetArray: nested writer not available");
    }
    inner_->aw_set_array(idx, *nested.inner_);
    nested.Destroy();
}

void ArrayWriter::SetRow(size_t idx, GenericRow&& row) {
    CHECK_AW("ArrayWriter");
    if (!row.inner_) {
        throw std::logic_error("ArrayWriter::SetRow: nested row not available");
    }
    inner_->aw_set_row(idx, *row.inner_);
}

void ArrayWriter::SetMap(size_t idx, MapWriter&& map) {
    CHECK_AW("ArrayWriter");
    if (!map.inner_) {
        throw std::logic_error("ArrayWriter::SetMap: nested map not available");
    }
    inner_->aw_set_map(idx, *map.inner_);
    map.Destroy();
}

// ============================================================================
// MapWriter — builder for map values backed by Rust MapWriterInner
// ============================================================================

MapWriter::MapWriter(size_t capacity, DataType key_type, DataType value_type)
    : key_type_(std::move(key_type)), value_type_(std::move(value_type)) {
    if (detail::is_compound(key_type_) || detail::is_compound(value_type_)) {
        inner_ = make_map_writer_arrow(capacity, detail::to_arrow_type(key_type_),
                                       detail::to_arrow_type(value_type_), value_type_.nullable());
        return;
    }

    // Keys are scalar; values may be a (possibly nested) ARRAY, so flatten them.
    auto value_flat = utils::flatten_array_type(value_type_);
    int32_t value_leaf = value_flat.nesting > 0 ? value_flat.leaf_type
                                                : static_cast<int32_t>(value_type_.id());
    uint32_t value_precision = static_cast<uint32_t>(
        value_flat.nesting > 0 ? value_flat.leaf_precision : value_type_.precision());
    uint32_t value_scale = static_cast<uint32_t>(
        value_flat.nesting > 0 ? value_flat.leaf_scale : value_type_.scale());
    uint32_t value_nesting = static_cast<uint32_t>(value_flat.nesting);

    auto box = ffi::new_map_writer(capacity,
                                   static_cast<int32_t>(key_type_.id()),
                                   static_cast<uint32_t>(key_type_.precision()),
                                   static_cast<uint32_t>(key_type_.scale()),
                                   value_leaf, value_precision, value_scale, value_nesting);
    inner_ = box.into_raw();
}

MapWriter::MapWriter(size_t capacity, std::shared_ptr<arrow::DataType> key_type,
                     std::shared_ptr<arrow::DataType> value_type)
    : key_type_(DataType::Int()), value_type_(DataType::Int()) {
    // Placeholders above; Rust holds the real key/value types.
    inner_ = make_map_writer_arrow(capacity, std::move(key_type), std::move(value_type),
                                   /*nullable=*/true);
}

MapWriter::~MapWriter() noexcept { Destroy(); }

void MapWriter::Destroy() noexcept {
    if (inner_) {
        rust::Box<ffi::MapWriterInner>::from_raw(inner_);
        inner_ = nullptr;
    }
}

MapWriter::MapWriter(MapWriter&& other) noexcept
    : inner_(other.inner_),
      key_type_(std::move(other.key_type_)),
      value_type_(std::move(other.value_type_)) {
    other.inner_ = nullptr;
}

MapWriter& MapWriter::operator=(MapWriter&& other) noexcept {
    if (this != &other) {
        Destroy();
        inner_ = other.inner_;
        key_type_ = std::move(other.key_type_);
        value_type_ = std::move(other.value_type_);
        other.inner_ = nullptr;
    }
    return *this;
}

bool MapWriter::Available() const { return inner_ != nullptr; }

void MapWriter::SetKeyBool(bool k) { CHECK_AW("MapWriter"); inner_->mw_key_bool(k); }
void MapWriter::SetKeyInt32(int32_t k) { CHECK_AW("MapWriter"); inner_->mw_key_i32(k); }
void MapWriter::SetKeyInt64(int64_t k) { CHECK_AW("MapWriter"); inner_->mw_key_i64(k); }
void MapWriter::SetKeyFloat32(float k) { CHECK_AW("MapWriter"); inner_->mw_key_f32(k); }
void MapWriter::SetKeyFloat64(double k) { CHECK_AW("MapWriter"); inner_->mw_key_f64(k); }
void MapWriter::SetKeyString(const std::string& k) { CHECK_AW("MapWriter"); inner_->mw_key_str(k); }
void MapWriter::SetKeyBytes(const std::vector<uint8_t>& k) {
    CHECK_AW("MapWriter");
    inner_->mw_key_bytes(rust::Slice<const uint8_t>(k.data(), k.size()));
}
void MapWriter::SetKeyDate(fluss::Date k) { CHECK_AW("MapWriter"); inner_->mw_key_date(k.days_since_epoch); }
void MapWriter::SetKeyTime(fluss::Time k) {
    CHECK_AW("MapWriter");
    inner_->mw_key_time(k.millis_since_midnight);
}
void MapWriter::SetKeyTimestamp(fluss::Timestamp k) {
    CHECK_AW("MapWriter");
    inner_->mw_key_timestamp(k.epoch_millis, k.nano_of_millisecond);
}
void MapWriter::SetKeyDecimal(const std::string& k) { CHECK_AW("MapWriter"); inner_->mw_key_decimal_str(k); }

void MapWriter::SetValueNull() { CHECK_AW("MapWriter"); inner_->mw_value_null(); }
void MapWriter::SetValueBool(bool v) { CHECK_AW("MapWriter"); inner_->mw_value_bool(v); }
void MapWriter::SetValueInt32(int32_t v) { CHECK_AW("MapWriter"); inner_->mw_value_i32(v); }
void MapWriter::SetValueInt64(int64_t v) { CHECK_AW("MapWriter"); inner_->mw_value_i64(v); }
void MapWriter::SetValueFloat32(float v) { CHECK_AW("MapWriter"); inner_->mw_value_f32(v); }
void MapWriter::SetValueFloat64(double v) { CHECK_AW("MapWriter"); inner_->mw_value_f64(v); }
void MapWriter::SetValueString(const std::string& v) { CHECK_AW("MapWriter"); inner_->mw_value_str(v); }
void MapWriter::SetValueBytes(const std::vector<uint8_t>& v) {
    CHECK_AW("MapWriter");
    inner_->mw_value_bytes(rust::Slice<const uint8_t>(v.data(), v.size()));
}
void MapWriter::SetValueDate(fluss::Date v) { CHECK_AW("MapWriter"); inner_->mw_value_date(v.days_since_epoch); }
void MapWriter::SetValueTime(fluss::Time v) {
    CHECK_AW("MapWriter");
    inner_->mw_value_time(v.millis_since_midnight);
}
void MapWriter::SetValueTimestamp(fluss::Timestamp v) {
    CHECK_AW("MapWriter");
    inner_->mw_value_timestamp(v.epoch_millis, v.nano_of_millisecond);
}
void MapWriter::SetValueDecimal(const std::string& v) {
    CHECK_AW("MapWriter");
    inner_->mw_value_decimal_str(v);
}
void MapWriter::SetValueRow(GenericRow&& v) {
    CHECK_AW("MapWriter");
    if (!v.inner_) {
        throw std::logic_error("MapWriter::SetValueRow: nested row not available");
    }
    inner_->mw_value_row(*v.inner_);
}
void MapWriter::SetValueMap(MapWriter&& v) {
    CHECK_AW("MapWriter");
    if (!v.inner_) {
        throw std::logic_error("MapWriter::SetValueMap: nested map not available");
    }
    inner_->mw_value_map(*v.inner_);
    v.Destroy();
}
void MapWriter::SetValueArray(ArrayWriter&& v) {
    CHECK_AW("MapWriter");
    if (!v.inner_) {
        throw std::logic_error("MapWriter::SetValueArray: nested array not available");
    }
    inner_->mw_value_array(*v.inner_);
    v.Destroy();
}

void MapWriter::Commit() { CHECK_AW("MapWriter"); inner_->mw_commit(); }

// ============================================================================
// Value — one recursive handle for complex (ARRAY/MAP/ROW) reads
// ============================================================================

Value::~Value() noexcept { Destroy(); }

void Value::Destroy() noexcept {
    if (inner_) {
        rust::Box<ffi::ValueInner>::from_raw(inner_);
        inner_ = nullptr;
    }
}

Value::Value(Value&& other) noexcept : inner_(other.inner_) { other.inner_ = nullptr; }

Value& Value::operator=(Value&& other) noexcept {
    if (this != &other) {
        Destroy();
        inner_ = other.inner_;
        other.inner_ = nullptr;
    }
    return *this;
}

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define CHECK_VALUE()                                                                  \
    do {                                                                               \
        if (!inner_) throw std::logic_error("Value: not available (moved-from)");      \
    } while (0)

TypeId Value::Type() const noexcept {
    assert(inner_ && "Value::Type called on moved-from instance");
    return static_cast<TypeId>(inner_->v_type());
}
bool Value::IsNull() const noexcept {
    assert(inner_ && "Value::IsNull called on moved-from instance");
    return inner_->v_is_null();
}
bool Value::GetBool() const { CHECK_VALUE(); return inner_->v_get_bool(); }
int32_t Value::GetInt32() const { CHECK_VALUE(); return inner_->v_get_i32(); }
int64_t Value::GetInt64() const { CHECK_VALUE(); return inner_->v_get_i64(); }
float Value::GetFloat32() const { CHECK_VALUE(); return inner_->v_get_f32(); }
double Value::GetFloat64() const { CHECK_VALUE(); return inner_->v_get_f64(); }
std::string Value::GetString() const { CHECK_VALUE(); return std::string(inner_->v_get_str()); }
std::vector<uint8_t> Value::GetBytes() const {
    CHECK_VALUE();
    auto rv = inner_->v_get_bytes();
    return {rv.data(), rv.data() + rv.size()};
}
fluss::Date Value::GetDate() const { CHECK_VALUE(); return fluss::Date{inner_->v_get_date_days()}; }
fluss::Time Value::GetTime() const {
    CHECK_VALUE();
    return fluss::Time{inner_->v_get_time_millis()};
}
fluss::Timestamp Value::GetTimestamp() const {
    CHECK_VALUE();
    return fluss::Timestamp{inner_->v_get_ts_millis(), inner_->v_get_ts_nanos()};
}
std::string Value::GetDecimalString() const {
    CHECK_VALUE();
    return std::string(inner_->v_get_decimal_str());
}
size_t Value::Size() const { CHECK_VALUE(); return inner_->v_size(); }
size_t Value::FieldCount() const { CHECK_VALUE(); return inner_->v_field_count(); }
Value Value::At(size_t i) const {
    CHECK_VALUE();
    auto box = inner_->v_at(i);
    return Value(box.into_raw());
}
Value Value::KeyAt(size_t i) const {
    CHECK_VALUE();
    auto box = inner_->v_key_at(i);
    return Value(box.into_raw());
}
Value Value::ValueAt(size_t i) const {
    CHECK_VALUE();
    auto box = inner_->v_value_at(i);
    return Value(box.into_raw());
}
Value Value::Field(size_t i) const {
    CHECK_VALUE();
    auto box = inner_->v_field(i);
    return Value(box.into_raw());
}
Value Value::Field(const std::string& name) const {
    CHECK_VALUE();
    auto box = inner_->v_field_by_name(name);
    return Value(box.into_raw());
}

#undef CHECK_VALUE

// ============================================================================
// GenericRow — write-only row backed by opaque Rust GenericRowInner
// ============================================================================

GenericRow::GenericRow() {
    auto box = ffi::new_generic_row(0);
    inner_ = box.into_raw();
}

GenericRow::GenericRow(size_t field_count) {
    auto box = ffi::new_generic_row(field_count);
    inner_ = box.into_raw();
}

GenericRow::~GenericRow() noexcept { Destroy(); }

void GenericRow::Destroy() noexcept {
    if (inner_) {
        rust::Box<ffi::GenericRowInner>::from_raw(inner_);
        inner_ = nullptr;
    }
    column_map_.reset();
}

GenericRow::GenericRow(GenericRow&& other) noexcept
    : inner_(other.inner_), column_map_(std::move(other.column_map_)) {
    other.inner_ = nullptr;
}

GenericRow& GenericRow::operator=(GenericRow&& other) noexcept {
    if (this != &other) {
        Destroy();
        inner_ = other.inner_;
        column_map_ = std::move(other.column_map_);
        other.inner_ = nullptr;
    }
    return *this;
}

bool GenericRow::Available() const { return inner_ != nullptr; }

void GenericRow::Reset() {
    CHECK_INNER("GenericRow");
    inner_->gr_reset();
}

void GenericRow::SetNull(size_t idx) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_null(idx);
}
void GenericRow::SetBool(size_t idx, bool v) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_bool(idx, v);
}
void GenericRow::SetInt32(size_t idx, int32_t v) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_i32(idx, v);
}
void GenericRow::SetInt64(size_t idx, int64_t v) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_i64(idx, v);
}
void GenericRow::SetFloat32(size_t idx, float v) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_f32(idx, v);
}
void GenericRow::SetFloat64(size_t idx, double v) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_f64(idx, v);
}

void GenericRow::SetString(size_t idx, std::string v) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_str(idx, v);
}

void GenericRow::SetBytes(size_t idx, std::vector<uint8_t> v) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_bytes(idx, rust::Slice<const uint8_t>(v.data(), v.size()));
}

void GenericRow::SetDate(size_t idx, fluss::Date d) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_date(idx, d.days_since_epoch);
}

void GenericRow::SetTime(size_t idx, fluss::Time t) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_time(idx, t.millis_since_midnight);
}

void GenericRow::SetTimestampNtz(size_t idx, fluss::Timestamp ts) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_ts_ntz(idx, ts.epoch_millis, ts.nano_of_millisecond);
}

void GenericRow::SetTimestampLtz(size_t idx, fluss::Timestamp ts) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_ts_ltz(idx, ts.epoch_millis, ts.nano_of_millisecond);
}

void GenericRow::SetDecimal(size_t idx, const std::string& value) {
    CHECK_INNER("GenericRow");
    inner_->gr_set_decimal_str(idx, value);
}

void GenericRow::SetArray(size_t idx, ArrayWriter&& writer) {
    CHECK_INNER("GenericRow");
    if (!writer.inner_) {
        throw std::logic_error("GenericRow::SetArray: ArrayWriter not available");
    }
    inner_->gr_set_array(idx, *writer.inner_);
    writer.Destroy();
}

void GenericRow::SetMap(size_t idx, MapWriter&& writer) {
    CHECK_INNER("GenericRow");
    if (!writer.inner_) {
        throw std::logic_error("GenericRow::SetMap: MapWriter not available");
    }
    inner_->gr_set_map(idx, *writer.inner_);
    writer.Destroy();
}

void GenericRow::SetRow(size_t idx, GenericRow&& nested) {
    CHECK_INNER("GenericRow");
    if (!nested.inner_) {
        throw std::logic_error("GenericRow::SetRow: nested row not available");
    }
    // gr_set_row moves the nested row's contents out; the emptied nested
    // handle is freed by `nested`'s own destructor at end of scope.
    inner_->gr_set_row(idx, *nested.inner_);
}

// ============================================================================
// ScanData — destructor must live in .cpp where rust::Box is visible
// ============================================================================

detail::ScanData::~ScanData() {
    if (raw) {
        rust::Box<ffi::ScanResultInner>::from_raw(raw);
    }
}

detail::PrefixData::~PrefixData() {
    if (raw) {
        rust::Box<ffi::PrefixLookupResultInner>::from_raw(raw);
    }
}

// ============================================================================
// RowView — zero-copy read-only row view for scan results
// ============================================================================

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define CHECK_DATA(name)                                                                 \
    do {                                                                                 \
        if (!data_) throw std::logic_error(name ": not available (moved-from or null)"); \
    } while (0)

size_t RowView::FieldCount() const { return data_ ? data_->raw->sv_field_count() : 0; }

TypeId RowView::GetType(size_t idx) const {
    CHECK_DATA("RowView");
    return static_cast<TypeId>(data_->raw->sv_column_type(idx));
}

bool RowView::IsNull(size_t idx) const {
    CHECK_DATA("RowView");
    return data_->raw->sv_is_null(bucket_idx_, rec_idx_, idx);
}
bool RowView::GetBool(size_t idx) const {
    CHECK_DATA("RowView");
    return data_->raw->sv_get_bool(bucket_idx_, rec_idx_, idx);
}
int32_t RowView::GetInt32(size_t idx) const {
    CHECK_DATA("RowView");
    return data_->raw->sv_get_i32(bucket_idx_, rec_idx_, idx);
}
int64_t RowView::GetInt64(size_t idx) const {
    CHECK_DATA("RowView");
    return data_->raw->sv_get_i64(bucket_idx_, rec_idx_, idx);
}
float RowView::GetFloat32(size_t idx) const {
    CHECK_DATA("RowView");
    return data_->raw->sv_get_f32(bucket_idx_, rec_idx_, idx);
}
double RowView::GetFloat64(size_t idx) const {
    CHECK_DATA("RowView");
    return data_->raw->sv_get_f64(bucket_idx_, rec_idx_, idx);
}

std::string_view RowView::GetString(size_t idx) const {
    CHECK_DATA("RowView");
    auto s = data_->raw->sv_get_str(bucket_idx_, rec_idx_, idx);
    return std::string_view(s.data(), s.size());
}

std::pair<const uint8_t*, size_t> RowView::GetBytes(size_t idx) const {
    CHECK_DATA("RowView");
    auto bytes = data_->raw->sv_get_bytes(bucket_idx_, rec_idx_, idx);
    return {bytes.data(), bytes.size()};
}

Date RowView::GetDate(size_t idx) const {
    CHECK_DATA("RowView");
    return Date{data_->raw->sv_get_date_days(bucket_idx_, rec_idx_, idx)};
}

Time RowView::GetTime(size_t idx) const {
    CHECK_DATA("RowView");
    return Time{data_->raw->sv_get_time_millis(bucket_idx_, rec_idx_, idx)};
}

Timestamp RowView::GetTimestamp(size_t idx) const {
    CHECK_DATA("RowView");
    return Timestamp{data_->raw->sv_get_ts_millis(bucket_idx_, rec_idx_, idx),
                     data_->raw->sv_get_ts_nanos(bucket_idx_, rec_idx_, idx)};
}

bool RowView::IsDecimal(size_t idx) const { return GetType(idx) == TypeId::Decimal; }

std::string RowView::GetDecimalString(size_t idx) const {
    CHECK_DATA("RowView");
    return std::string(data_->raw->sv_get_decimal_str(bucket_idx_, rec_idx_, idx));
}

Value RowView::GetValue(size_t idx) const {
    CHECK_DATA("RowView");
    auto box = data_->raw->sv_get_value(bucket_idx_, rec_idx_, idx);
    return Value(box.into_raw());
}

Value RowView::GetValue(const std::string& name) const { return GetValue(Resolve(name)); }

// ============================================================================
// PrefixLookupResult / PrefixRowView — read path for prefix lookups
// ============================================================================

size_t PrefixLookupResult::Size() const { return data_ ? data_->raw->plv_row_count() : 0; }

size_t PrefixRowView::FieldCount() const { return data_ ? data_->raw->plv_field_count() : 0; }

TypeId PrefixRowView::GetType(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    return static_cast<TypeId>(data_->raw->plv_column_type(idx));
}

bool PrefixRowView::IsNull(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    return data_->raw->plv_is_null(rec_idx_, idx);
}
bool PrefixRowView::GetBool(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    return data_->raw->plv_get_bool(rec_idx_, idx);
}
int32_t PrefixRowView::GetInt32(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    return data_->raw->plv_get_i32(rec_idx_, idx);
}
int64_t PrefixRowView::GetInt64(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    return data_->raw->plv_get_i64(rec_idx_, idx);
}
float PrefixRowView::GetFloat32(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    return data_->raw->plv_get_f32(rec_idx_, idx);
}
double PrefixRowView::GetFloat64(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    return data_->raw->plv_get_f64(rec_idx_, idx);
}
std::string_view PrefixRowView::GetString(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    auto s = data_->raw->plv_get_str(rec_idx_, idx);
    return std::string_view(s.data(), s.size());
}
std::pair<const uint8_t*, size_t> PrefixRowView::GetBytes(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    auto bytes = data_->raw->plv_get_bytes(rec_idx_, idx);
    return {bytes.data(), bytes.size()};
}
Date PrefixRowView::GetDate(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    return Date{data_->raw->plv_get_date_days(rec_idx_, idx)};
}
Time PrefixRowView::GetTime(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    return Time{data_->raw->plv_get_time_millis(rec_idx_, idx)};
}
Timestamp PrefixRowView::GetTimestamp(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    return Timestamp{data_->raw->plv_get_ts_millis(rec_idx_, idx),
                     data_->raw->plv_get_ts_nanos(rec_idx_, idx)};
}
bool PrefixRowView::IsDecimal(size_t idx) const { return GetType(idx) == TypeId::Decimal; }
std::string PrefixRowView::GetDecimalString(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    return std::string(data_->raw->plv_get_decimal_str(rec_idx_, idx));
}

Value PrefixRowView::GetValue(size_t idx) const {
    CHECK_DATA("PrefixRowView");
    auto box = data_->raw->plv_get_value(rec_idx_, idx);
    return Value(box.into_raw());
}
Value PrefixRowView::GetValue(const std::string& name) const { return GetValue(Resolve(name)); }

// ============================================================================
// ScanRecords — backed by opaque Rust ScanResultInner
// ============================================================================

// ScanRecords constructor, destructor, move operations are all defaulted in the header.

size_t ScanRecords::Count() const { return data_ ? data_->raw->sv_record_count() : 0; }

bool ScanRecords::IsEmpty() const { return Count() == 0; }

ScanRecord ScanRecords::RecordAt(size_t bucket, size_t rec_idx) const {
    if (!data_) {
        throw std::logic_error("ScanRecords: not available (moved-from or null)");
    }
    return ScanRecord{data_->raw->sv_offset(bucket, rec_idx),
                      data_->raw->sv_timestamp(bucket, rec_idx),
                      static_cast<ChangeType>(data_->raw->sv_change_type(bucket, rec_idx)),
                      RowView(data_, bucket, rec_idx)};
}

static TableBucket to_table_bucket(const ffi::FfiBucketInfo& g) {
    return TableBucket{g.table_id, g.bucket_id,
                       g.has_partition_id ? std::optional<int64_t>(g.partition_id) : std::nullopt};
}

size_t ScanRecords::BucketCount() const { return data_ ? data_->raw->sv_bucket_infos().size() : 0; }

ScanRecord ScanRecords::Iterator::operator*() const {
    return owner_->RecordAt(bucket_idx_, rec_idx_);
}

ScanRecords::Iterator ScanRecords::begin() const { return Iterator(this, 0, 0); }

ScanRecords::Iterator& ScanRecords::Iterator::operator++() {
    ++rec_idx_;
    if (owner_->data_) {
        const auto& infos = owner_->data_->raw->sv_bucket_infos();
        while (bucket_idx_ < infos.size() && rec_idx_ >= infos[bucket_idx_].record_count) {
            rec_idx_ = 0;
            ++bucket_idx_;
        }
    }
    return *this;
}

std::vector<TableBucket> ScanRecords::Buckets() const {
    std::vector<TableBucket> result;
    if (!data_) return result;
    const auto& infos = data_->raw->sv_bucket_infos();
    result.reserve(infos.size());
    for (const auto& g : infos) {
        result.push_back(to_table_bucket(g));
    }
    return result;
}

BucketRecords ScanRecords::Records(const TableBucket& bucket) const {
    if (!data_) {
        return BucketRecords({}, bucket, 0, 0);
    }
    const auto& infos = data_->raw->sv_bucket_infos();
    for (size_t i = 0; i < infos.size(); ++i) {
        TableBucket tb = to_table_bucket(infos[i]);
        if (tb == bucket) {
            return BucketRecords(data_, std::move(tb), i, infos[i].record_count);
        }
    }
    return BucketRecords({}, bucket, 0, 0);
}

BucketRecords ScanRecords::BucketAt(size_t idx) const {
    if (!data_) {
        throw std::logic_error("ScanRecords: not available (moved-from or null)");
    }
    const auto& infos = data_->raw->sv_bucket_infos();
    if (idx >= infos.size()) {
        throw std::out_of_range("ScanRecords::BucketAt: index " + std::to_string(idx) +
                                " out of range (" + std::to_string(infos.size()) + " buckets)");
    }
    return BucketRecords(data_, to_table_bucket(infos[idx]), idx, infos[idx].record_count);
}

ScanRecord BucketRecords::operator[](size_t idx) const {
    if (idx >= count_) {
        throw std::out_of_range("BucketRecords: index " + std::to_string(idx) + " out of range (" +
                                std::to_string(count_) + " records)");
    }
    return ScanRecord{data_->raw->sv_offset(bucket_idx_, idx),
                      data_->raw->sv_timestamp(bucket_idx_, idx),
                      static_cast<ChangeType>(data_->raw->sv_change_type(bucket_idx_, idx)),
                      RowView(data_, bucket_idx_, idx)};
}

ScanRecord BucketRecords::Iterator::operator*() const { return owner_->operator[](idx_); }

// ============================================================================
// LookupResult — backed by opaque Rust LookupResultInner
// ============================================================================

LookupResult::LookupResult() noexcept = default;

LookupResult::~LookupResult() noexcept { Destroy(); }

void LookupResult::Destroy() noexcept {
    if (inner_) {
        rust::Box<ffi::LookupResultInner>::from_raw(inner_);
        inner_ = nullptr;
        column_map_.reset();
    }
}

LookupResult::LookupResult(LookupResult&& other) noexcept
    : inner_(other.inner_), column_map_(std::move(other.column_map_)) {
    other.inner_ = nullptr;
}

LookupResult& LookupResult::operator=(LookupResult&& other) noexcept {
    if (this != &other) {
        Destroy();
        inner_ = other.inner_;
        column_map_ = std::move(other.column_map_);
        other.inner_ = nullptr;
    }
    return *this;
}

void LookupResult::BuildColumnMap() const {
    if (!inner_) return;
    auto map = std::make_shared<detail::ColumnMap>();
    auto count = inner_->lv_field_count();
    for (size_t i = 0; i < count; ++i) {
        auto name = inner_->lv_column_name(i);
        (*map)[std::string(name.data(), name.size())] = {
            i, static_cast<TypeId>(inner_->lv_column_type(i))};
    }
    column_map_ = std::move(map);
}

bool LookupResult::Found() const { return inner_ && inner_->lv_found(); }

size_t LookupResult::FieldCount() const { return inner_ ? inner_->lv_field_count() : 0; }

TypeId LookupResult::GetType(size_t idx) const {
    CHECK_INNER("LookupResult");
    return static_cast<TypeId>(inner_->lv_column_type(idx));
}

bool LookupResult::IsNull(size_t idx) const {
    CHECK_INNER("LookupResult");
    return inner_->lv_is_null(idx);
}
bool LookupResult::GetBool(size_t idx) const {
    CHECK_INNER("LookupResult");
    return inner_->lv_get_bool(idx);
}
int32_t LookupResult::GetInt32(size_t idx) const {
    CHECK_INNER("LookupResult");
    return inner_->lv_get_i32(idx);
}
int64_t LookupResult::GetInt64(size_t idx) const {
    CHECK_INNER("LookupResult");
    return inner_->lv_get_i64(idx);
}
float LookupResult::GetFloat32(size_t idx) const {
    CHECK_INNER("LookupResult");
    return inner_->lv_get_f32(idx);
}
double LookupResult::GetFloat64(size_t idx) const {
    CHECK_INNER("LookupResult");
    return inner_->lv_get_f64(idx);
}

std::string_view LookupResult::GetString(size_t idx) const {
    CHECK_INNER("LookupResult");
    auto s = inner_->lv_get_str(idx);
    return std::string_view(s.data(), s.size());
}

std::pair<const uint8_t*, size_t> LookupResult::GetBytes(size_t idx) const {
    CHECK_INNER("LookupResult");
    auto bytes = inner_->lv_get_bytes(idx);
    return {bytes.data(), bytes.size()};
}

Date LookupResult::GetDate(size_t idx) const {
    CHECK_INNER("LookupResult");
    return Date{inner_->lv_get_date_days(idx)};
}

Time LookupResult::GetTime(size_t idx) const {
    CHECK_INNER("LookupResult");
    return Time{inner_->lv_get_time_millis(idx)};
}

Timestamp LookupResult::GetTimestamp(size_t idx) const {
    CHECK_INNER("LookupResult");
    return Timestamp{inner_->lv_get_ts_millis(idx), inner_->lv_get_ts_nanos(idx)};
}

bool LookupResult::IsDecimal(size_t idx) const { return GetType(idx) == TypeId::Decimal; }

std::string LookupResult::GetDecimalString(size_t idx) const {
    CHECK_INNER("LookupResult");
    return std::string(inner_->lv_get_decimal_str(idx));
}

Value LookupResult::GetValue(size_t idx) const {
    CHECK_INNER("LookupResult");
    auto box = inner_->lv_get_value(idx);
    return Value(box.into_raw());
}

Value LookupResult::GetValue(const std::string& name) const {
    return GetValue(Resolve(name));
}

// ============================================================================
// Table
// ============================================================================

Table::Table() noexcept = default;

Table::Table(ffi::Table* table) noexcept : table_(table) {}

Table::~Table() noexcept { Destroy(); }

void Table::Destroy() noexcept {
    if (table_) {
        ffi::delete_table(table_);
        table_ = nullptr;
    }
}

Table::Table(Table&& other) noexcept
    : table_(other.table_), column_map_(std::move(other.column_map_)) {
    other.table_ = nullptr;
}

Table& Table::operator=(Table&& other) noexcept {
    if (this != &other) {
        Destroy();
        table_ = other.table_;
        column_map_ = std::move(other.column_map_);
        other.table_ = nullptr;
    }
    return *this;
}

bool Table::Available() const { return table_ != nullptr; }

TableAppend Table::NewAppend() { return TableAppend(table_); }

TableUpsert Table::NewUpsert() { return TableUpsert(table_); }

TableLookup Table::NewLookup() { return TableLookup(table_); }

TableScan Table::NewScan() { return TableScan(table_); }

Result Table::NewPrefixLookup(std::vector<std::string> lookup_columns, PrefixLookuper& out) {
    if (table_ == nullptr) {
        return utils::make_client_error("Table not available");
    }

    rust::Vec<rust::String> cols;
    cols.reserve(lookup_columns.size());
    for (const auto& c : lookup_columns) {
        cols.push_back(rust::String(c));
    }

    auto ffi_result = table_->new_prefix_lookuper(std::move(cols));
    auto result = utils::from_ffi_result(ffi_result.result);
    if (result.Ok()) {
        out = PrefixLookuper(utils::ptr_from_ffi<ffi::PrefixLookuper>(ffi_result));
    }
    return result;
}

const std::shared_ptr<GenericRow::ColumnMap>& Table::GetColumnMap() const {
    if (!column_map_ && Available()) {
        auto info = GetTableInfo();
        column_map_ = std::make_shared<GenericRow::ColumnMap>();
        for (size_t i = 0; i < info.schema.columns.size(); ++i) {
            (*column_map_)[info.schema.columns[i].name] = {i,
                                                           info.schema.columns[i].data_type.id()};
        }
    }
    return column_map_;
}

GenericRow Table::NewRow() const {
    GenericRow row;
    row.column_map_ = GetColumnMap();
    return row;
}

TableInfo Table::GetTableInfo() const {
    if (!Available()) {
        return TableInfo{};
    }
    auto ffi_info = table_->get_table_info_from_table();
    return utils::from_ffi_table_info(ffi_info);
}

TablePath Table::GetTablePath() const {
    if (!Available()) {
        return TablePath{};
    }
    auto ffi_path = table_->get_table_path();
    return TablePath{std::string(ffi_path.database_name), std::string(ffi_path.table_name)};
}

bool Table::HasPrimaryKey() const {
    if (!Available()) {
        return false;
    }
    return table_->has_primary_key();
}

// ============================================================================
// TableAppend
// ============================================================================

TableAppend::TableAppend(ffi::Table* table) noexcept : table_(table) {}

Result TableAppend::CreateWriter(AppendWriter& out) {
    if (table_ == nullptr) {
        return utils::make_client_error("Table not available");
    }

    auto ffi_result = table_->new_append_writer();
    auto result = utils::from_ffi_result(ffi_result.result);
    if (result.Ok()) {
        out = AppendWriter(utils::ptr_from_ffi<ffi::AppendWriter>(ffi_result));
    }
    return result;
}

// ============================================================================
// TableUpsert
// ============================================================================

TableUpsert::TableUpsert(ffi::Table* table) noexcept : table_(table) {}

TableUpsert& TableUpsert::PartialUpdateByIndex(std::vector<size_t> column_indices) {
    if (column_indices.empty()) {
        throw std::invalid_argument("PartialUpdateByIndex requires at least one column");
    }
    column_indices_ = std::move(column_indices);
    column_names_.clear();
    return *this;
}

TableUpsert& TableUpsert::PartialUpdateByName(std::vector<std::string> column_names) {
    if (column_names.empty()) {
        throw std::invalid_argument("PartialUpdateByName requires at least one column");
    }
    column_names_ = std::move(column_names);
    column_indices_.clear();
    return *this;
}

std::vector<size_t> TableUpsert::ResolveNameProjection() const {
    auto ffi_info = table_->get_table_info_from_table();
    const auto& columns = ffi_info.schema.columns;

    std::vector<size_t> indices;
    for (const auto& name : column_names_) {
        bool found = false;
        for (size_t i = 0; i < columns.size(); ++i) {
            if (std::string(columns[i].name) == name) {
                indices.push_back(i);
                found = true;
                break;
            }
        }
        if (!found) {
            throw std::runtime_error("Column '" + name + "' not found");
        }
    }
    return indices;
}

Result TableUpsert::CreateWriter(UpsertWriter& out) {
    if (table_ == nullptr) {
        return utils::make_client_error("Table not available");
    }

    try {
        auto resolved_indices = !column_names_.empty() ? ResolveNameProjection() : column_indices_;

        rust::Vec<size_t> rust_indices;
        for (size_t idx : resolved_indices) {
            rust_indices.push_back(idx);
        }
        auto ffi_result = table_->create_upsert_writer(std::move(rust_indices));
        auto result = utils::from_ffi_result(ffi_result.result);
        if (result.Ok()) {
            out = UpsertWriter(utils::ptr_from_ffi<ffi::UpsertWriter>(ffi_result));
        }
        return result;
    } catch (const std::exception& e) {
        // ResolveNameProjection() may throw
        return utils::make_client_error(e.what());
    }
}

// ============================================================================
// TableLookup
// ============================================================================

TableLookup::TableLookup(ffi::Table* table) noexcept : table_(table) {}

Result TableLookup::CreateLookuper(Lookuper& out) {
    if (table_ == nullptr) {
        return utils::make_client_error("Table not available");
    }

    auto ffi_result = table_->new_lookuper();
    auto result = utils::from_ffi_result(ffi_result.result);
    if (result.Ok()) {
        out = Lookuper(utils::ptr_from_ffi<ffi::Lookuper>(ffi_result));
    }
    return result;
}

// ============================================================================
// TableScan
// ============================================================================

TableScan::TableScan(ffi::Table* table) noexcept : table_(table) {}

TableScan& TableScan::ProjectByIndex(std::vector<size_t> column_indices) {
    projection_ = std::move(column_indices);
    name_projection_.clear();
    return *this;
}

TableScan& TableScan::ProjectByName(std::vector<std::string> column_names) {
    name_projection_ = std::move(column_names);
    projection_.clear();
    return *this;
}

std::vector<size_t> TableScan::ResolveNameProjection() const {
    auto ffi_info = table_->get_table_info_from_table();
    const auto& columns = ffi_info.schema.columns;

    std::vector<size_t> indices;
    for (const auto& name : name_projection_) {
        bool found = false;
        for (size_t i = 0; i < columns.size(); ++i) {
            if (std::string(columns[i].name) == name) {
                indices.push_back(i);
                found = true;
                break;
            }
        }
        if (!found) {
            throw std::runtime_error("Column '" + name + "' not found");
        }
    }
    return indices;
}

Result TableScan::CreateLogScanner(LogScanner& out) { return DoCreateScanner(out, false); }

Result TableScan::CreateRecordBatchLogScanner(LogScanner& out) {
    return DoCreateScanner(out, true);
}

Result TableScan::DoCreateScanner(LogScanner& out, bool is_record_batch) {
    if (table_ == nullptr) {
        return utils::make_client_error("Table not available");
    }
    if (limit_.has_value()) {
        return utils::make_client_error(
            "Log scanners don't support limit pushdown; use CreateBucketBatchScanner()");
    }

    try {
        auto resolved_indices = !name_projection_.empty() ? ResolveNameProjection() : projection_;
        rust::Vec<size_t> rust_indices;
        for (size_t idx : resolved_indices) {
            rust_indices.push_back(idx);
        }
        auto ffi_result = table_->create_scanner(std::move(rust_indices), is_record_batch);
        auto result = utils::from_ffi_result(ffi_result.result);
        if (result.Ok()) {
            out.scanner_ = utils::ptr_from_ffi<ffi::LogScanner>(ffi_result);
        }
        return result;
    } catch (const std::exception& e) {
        // ResolveNameProjection() may throw
        return utils::make_client_error(e.what());
    }
}

TableScan& TableScan::Limit(int32_t row_number) {
    limit_ = row_number;
    return *this;
}

Result TableScan::CreateBucketBatchScanner(const TableBucket& bucket, BatchScanner& out) {
    if (table_ == nullptr) {
        return utils::make_client_error("Table not available");
    }
    if (!limit_.has_value()) {
        return utils::make_client_error(
            "CreateBucketBatchScanner requires a limit set via Limit()");
    }

    try {
        auto resolved_indices = !name_projection_.empty() ? ResolveNameProjection() : projection_;
        rust::Vec<size_t> rust_indices;
        for (size_t idx : resolved_indices) {
            rust_indices.push_back(idx);
        }
        int64_t partition_id = bucket.partition_id.value_or(-1);
        auto ffi_result = table_->create_bucket_batch_scanner(
            std::move(rust_indices), *limit_, bucket.table_id, partition_id, bucket.bucket_id);
        auto result = utils::from_ffi_result(ffi_result.result);
        if (result.Ok()) {
            out.scanner_ = utils::ptr_from_ffi<ffi::BatchScanner>(ffi_result);
            out.bucket_ = bucket;
        }
        return result;
    } catch (const std::exception& e) {
        // ResolveNameProjection() may throw
        return utils::make_client_error(e.what());
    }
}

// ============================================================================
// WriteResult
// ============================================================================

WriteResult::WriteResult() noexcept = default;

WriteResult::WriteResult(ffi::WriteResult* inner) noexcept : inner_(inner) {}

WriteResult::~WriteResult() noexcept { Destroy(); }

void WriteResult::Destroy() noexcept {
    if (inner_) {
        ffi::delete_write_result(inner_);
        inner_ = nullptr;
    }
}

WriteResult::WriteResult(WriteResult&& other) noexcept : inner_(other.inner_) {
    other.inner_ = nullptr;
}

WriteResult& WriteResult::operator=(WriteResult&& other) noexcept {
    if (this != &other) {
        Destroy();
        inner_ = other.inner_;
        other.inner_ = nullptr;
    }
    return *this;
}

bool WriteResult::Available() const { return inner_ != nullptr; }

Result WriteResult::Wait() {
    if (!Available()) {
        return utils::make_ok();
    }

    auto ffi_result = inner_->wait();
    return utils::from_ffi_result(ffi_result);
}

// ============================================================================
// AppendWriter
// ============================================================================

AppendWriter::AppendWriter() noexcept = default;

AppendWriter::AppendWriter(ffi::AppendWriter* writer) noexcept : writer_(writer) {}

AppendWriter::~AppendWriter() noexcept { Destroy(); }

void AppendWriter::Destroy() noexcept {
    if (writer_) {
        ffi::delete_append_writer(writer_);
        writer_ = nullptr;
    }
}

AppendWriter::AppendWriter(AppendWriter&& other) noexcept : writer_(other.writer_) {
    other.writer_ = nullptr;
}

AppendWriter& AppendWriter::operator=(AppendWriter&& other) noexcept {
    if (this != &other) {
        Destroy();
        writer_ = other.writer_;
        other.writer_ = nullptr;
    }
    return *this;
}

bool AppendWriter::Available() const { return writer_ != nullptr; }

Result AppendWriter::Append(const GenericRow& row) {
    WriteResult wr;
    return Append(row, wr);
}

Result AppendWriter::Append(const GenericRow& row, WriteResult& out) {
    if (!Available()) {
        return utils::make_client_error("AppendWriter not available");
    }
    if (!row.Available()) {
        return utils::make_client_error("GenericRow not available");
    }

    auto ffi_result = writer_->append(*row.inner_);
    auto result = utils::from_ffi_result(ffi_result.result);
    if (result.Ok()) {
        out = WriteResult(utils::ptr_from_ffi<ffi::WriteResult>(ffi_result));
    }
    return result;
}

Result AppendWriter::AppendArrowBatch(const std::shared_ptr<arrow::RecordBatch>& batch) {
    WriteResult wr;
    return AppendArrowBatch(batch, wr);
}

Result AppendWriter::AppendArrowBatch(const std::shared_ptr<arrow::RecordBatch>& batch,
                                      WriteResult& out) {
    if (!Available()) {
        return utils::make_client_error("AppendWriter not available");
    }
    if (!batch) {
        return utils::make_client_error("Arrow RecordBatch is null");
    }

    // Export via Arrow C Data Interface
    struct ArrowArray c_array;
    struct ArrowSchema c_schema;
    auto status = arrow::ExportRecordBatch(*batch, &c_array, &c_schema);
    if (!status.ok()) {
        return utils::make_client_error("Failed to export Arrow batch: " + status.ToString());
    }

    // Heap-allocate for Rust ownership transfer
    auto* array_heap = new ArrowArray(std::move(c_array));
    auto* schema_heap = new ArrowSchema(std::move(c_schema));

    // Rust takes ownership of both pointers immediately via Box::from_raw(),
    // so after this call C++ must NOT free them.
    auto ffi_result = writer_->append_arrow_batch(reinterpret_cast<size_t>(array_heap),
                                                  reinterpret_cast<size_t>(schema_heap));
    auto result = utils::from_ffi_result(ffi_result.result);
    if (result.Ok()) {
        out.Destroy();
        out.inner_ = utils::ptr_from_ffi<ffi::WriteResult>(ffi_result);
    }
    return result;
}

Result AppendWriter::Flush() {
    if (!Available()) {
        return utils::make_client_error("AppendWriter not available");
    }

    auto ffi_result = writer_->flush();
    return utils::from_ffi_result(ffi_result);
}

// ============================================================================
// UpsertWriter
// ============================================================================

UpsertWriter::UpsertWriter() noexcept = default;

UpsertWriter::UpsertWriter(ffi::UpsertWriter* writer) noexcept : writer_(writer) {}

UpsertWriter::~UpsertWriter() noexcept { Destroy(); }

void UpsertWriter::Destroy() noexcept {
    if (writer_) {
        ffi::delete_upsert_writer(writer_);
        writer_ = nullptr;
    }
}

UpsertWriter::UpsertWriter(UpsertWriter&& other) noexcept : writer_(other.writer_) {
    other.writer_ = nullptr;
}

UpsertWriter& UpsertWriter::operator=(UpsertWriter&& other) noexcept {
    if (this != &other) {
        Destroy();
        writer_ = other.writer_;
        other.writer_ = nullptr;
    }
    return *this;
}

bool UpsertWriter::Available() const { return writer_ != nullptr; }

Result UpsertWriter::Upsert(const GenericRow& row) {
    WriteResult wr;
    return Upsert(row, wr);
}

Result UpsertWriter::Upsert(const GenericRow& row, WriteResult& out) {
    if (!Available()) {
        return utils::make_client_error("UpsertWriter not available");
    }
    if (!row.Available()) {
        return utils::make_client_error("GenericRow not available");
    }

    auto ffi_result = writer_->upsert(*row.inner_);
    auto result = utils::from_ffi_result(ffi_result.result);
    if (result.Ok()) {
        out = WriteResult(utils::ptr_from_ffi<ffi::WriteResult>(ffi_result));
    }
    return result;
}

Result UpsertWriter::Delete(const GenericRow& row) {
    WriteResult wr;
    return Delete(row, wr);
}

Result UpsertWriter::Delete(const GenericRow& row, WriteResult& out) {
    if (!Available()) {
        return utils::make_client_error("UpsertWriter not available");
    }
    if (!row.Available()) {
        return utils::make_client_error("GenericRow not available");
    }

    auto ffi_result = writer_->delete_row(*row.inner_);
    auto result = utils::from_ffi_result(ffi_result.result);
    if (result.Ok()) {
        out = WriteResult(utils::ptr_from_ffi<ffi::WriteResult>(ffi_result));
    }
    return result;
}

Result UpsertWriter::Flush() {
    if (!Available()) {
        return utils::make_client_error("UpsertWriter not available");
    }

    auto ffi_result = writer_->upsert_flush();
    return utils::from_ffi_result(ffi_result);
}

// ============================================================================
// Lookuper
// ============================================================================

Lookuper::Lookuper() noexcept = default;

Lookuper::Lookuper(ffi::Lookuper* lookuper) noexcept : lookuper_(lookuper) {}

Lookuper::~Lookuper() noexcept { Destroy(); }

void Lookuper::Destroy() noexcept {
    if (lookuper_) {
        ffi::delete_lookuper(lookuper_);
        lookuper_ = nullptr;
    }
}

Lookuper::Lookuper(Lookuper&& other) noexcept : lookuper_(other.lookuper_) {
    other.lookuper_ = nullptr;
}

Lookuper& Lookuper::operator=(Lookuper&& other) noexcept {
    if (this != &other) {
        Destroy();
        lookuper_ = other.lookuper_;
        other.lookuper_ = nullptr;
    }
    return *this;
}

bool Lookuper::Available() const { return lookuper_ != nullptr; }

Result Lookuper::Lookup(const GenericRow& pk_row, LookupResult& out) {
    if (!Available()) {
        return utils::make_client_error("Lookuper not available");
    }
    if (!pk_row.Available()) {
        return utils::make_client_error("GenericRow not available");
    }

    auto result_box = lookuper_->lookup(*pk_row.inner_);
    if (result_box->lv_has_error()) {
        return utils::make_error(result_box->lv_error_code(),
                                 std::string(result_box->lv_error_message()));
    }

    out.Destroy();
    out.inner_ = result_box.into_raw();
    return utils::make_ok();
}

// ============================================================================
// PrefixLookuper
// ============================================================================

PrefixLookuper::PrefixLookuper() noexcept = default;

PrefixLookuper::PrefixLookuper(ffi::PrefixLookuper* lookuper) noexcept : lookuper_(lookuper) {}

PrefixLookuper::~PrefixLookuper() noexcept { Destroy(); }

void PrefixLookuper::Destroy() noexcept {
    if (lookuper_) {
        ffi::delete_prefix_lookuper(lookuper_);
        lookuper_ = nullptr;
    }
}

PrefixLookuper::PrefixLookuper(PrefixLookuper&& other) noexcept : lookuper_(other.lookuper_) {
    other.lookuper_ = nullptr;
}

PrefixLookuper& PrefixLookuper::operator=(PrefixLookuper&& other) noexcept {
    if (this != &other) {
        Destroy();
        lookuper_ = other.lookuper_;
        other.lookuper_ = nullptr;
    }
    return *this;
}

bool PrefixLookuper::Available() const { return lookuper_ != nullptr; }

Result PrefixLookuper::PrefixLookup(const GenericRow& prefix_row, PrefixLookupResult& out) {
    if (!Available()) {
        return utils::make_client_error("PrefixLookuper not available");
    }
    if (!prefix_row.Available()) {
        return utils::make_client_error("GenericRow not available");
    }

    auto result_box = lookuper_->prefix_lookup(*prefix_row.inner_);
    if (result_box->plv_has_error()) {
        return utils::make_error(result_box->plv_error_code(),
                                 std::string(result_box->plv_error_message()));
    }

    // Take ownership of the FFI box first (~PrefixData calls from_raw), so the
    // column-map loop below can't leak it if a string/map allocation throws.
    // The map is built eagerly and shared by all PrefixRowViews.
    auto data = std::make_shared<detail::PrefixData>(result_box.into_raw(), detail::ColumnMap{});
    auto col_count = data->raw->plv_field_count();
    for (size_t i = 0; i < col_count; ++i) {
        auto name = data->raw->plv_column_name(i);
        data->columns[std::string(name.data(), name.size())] = {
            i, static_cast<TypeId>(data->raw->plv_column_type(i))};
    }
    out.data_ = std::move(data);
    return utils::make_ok();
}

// ============================================================================
// LogScanner
// ============================================================================

LogScanner::LogScanner() noexcept = default;

LogScanner::LogScanner(ffi::LogScanner* scanner) noexcept : scanner_(scanner) {}

LogScanner::~LogScanner() noexcept { Destroy(); }

void LogScanner::Destroy() noexcept {
    if (scanner_) {
        ffi::delete_log_scanner(scanner_);
        scanner_ = nullptr;
    }
}

LogScanner::LogScanner(LogScanner&& other) noexcept : scanner_(other.scanner_) {
    other.scanner_ = nullptr;
}

LogScanner& LogScanner::operator=(LogScanner&& other) noexcept {
    if (this != &other) {
        Destroy();
        scanner_ = other.scanner_;
        other.scanner_ = nullptr;
    }
    return *this;
}

bool LogScanner::Available() const { return scanner_ != nullptr; }

Result LogScanner::Subscribe(int32_t bucket_id, int64_t start_offset) {
    if (!Available()) {
        return utils::make_client_error("LogScanner not available");
    }

    auto ffi_result = scanner_->subscribe(bucket_id, start_offset);
    return utils::from_ffi_result(ffi_result);
}

Result LogScanner::Subscribe(const std::vector<BucketSubscription>& bucket_offsets) {
    if (!Available()) {
        return utils::make_client_error("LogScanner not available");
    }

    rust::Vec<ffi::FfiBucketSubscription> rust_subs;
    for (const auto& sub : bucket_offsets) {
        ffi::FfiBucketSubscription ffi_sub;
        ffi_sub.bucket_id = sub.bucket_id;
        ffi_sub.offset = sub.offset;
        rust_subs.push_back(ffi_sub);
    }

    auto ffi_result = scanner_->subscribe_buckets(std::move(rust_subs));
    return utils::from_ffi_result(ffi_result);
}

Result LogScanner::SubscribePartitionBuckets(int64_t partition_id, int32_t bucket_id,
                                             int64_t start_offset) {
    if (!Available()) {
        return utils::make_client_error("LogScanner not available");
    }

    auto ffi_result = scanner_->subscribe_partition(partition_id, bucket_id, start_offset);
    return utils::from_ffi_result(ffi_result);
}

Result LogScanner::SubscribePartitionBuckets(
    const std::vector<PartitionBucketSubscription>& subscriptions) {
    if (!Available()) {
        return utils::make_client_error("LogScanner not available");
    }

    rust::Vec<ffi::FfiPartitionBucketSubscription> rust_subs;
    for (const auto& sub : subscriptions) {
        ffi::FfiPartitionBucketSubscription ffi_sub;
        ffi_sub.partition_id = sub.partition_id;
        ffi_sub.bucket_id = sub.bucket_id;
        ffi_sub.offset = sub.offset;
        rust_subs.push_back(ffi_sub);
    }

    auto ffi_result = scanner_->subscribe_partition_buckets(std::move(rust_subs));
    return utils::from_ffi_result(ffi_result);
}

Result LogScanner::Unsubscribe(int32_t bucket_id) {
    if (!Available()) {
        return utils::make_client_error("LogScanner not available");
    }

    auto ffi_result = scanner_->unsubscribe(bucket_id);
    return utils::from_ffi_result(ffi_result);
}

Result LogScanner::UnsubscribePartition(int64_t partition_id, int32_t bucket_id) {
    if (!Available()) {
        return utils::make_client_error("LogScanner not available");
    }

    auto ffi_result = scanner_->unsubscribe_partition(partition_id, bucket_id);
    return utils::from_ffi_result(ffi_result);
}

Result LogScanner::Poll(int64_t timeout_ms, ScanRecords& out) {
    if (!Available()) {
        return utils::make_client_error("LogScanner not available");
    }

    auto result_box = scanner_->poll(timeout_ms);
    if (result_box->sv_has_error()) {
        return utils::make_error(result_box->sv_error_code(),
                                 std::string(result_box->sv_error_message()));
    }

    // Wrap raw pointer in ScanData immediately so it's never leaked on exception.
    auto data = std::make_shared<detail::ScanData>(result_box.into_raw(), detail::ColumnMap{});
    // Build column map eagerly — shared by all RowViews/BucketRecords.
    auto col_count = data->raw->sv_column_count();
    for (size_t i = 0; i < col_count; ++i) {
        auto name = data->raw->sv_column_name(i);
        data->columns[std::string(name.data(), name.size())] = {
            i, static_cast<TypeId>(data->raw->sv_column_type(i))};
    }
    out.data_ = std::move(data);
    return utils::make_ok();
}

ArrowRecordBatch::ArrowRecordBatch(std::shared_ptr<arrow::RecordBatch> batch, int64_t table_id,
                                   int64_t partition_id, int32_t bucket_id,
                                   int64_t base_offset) noexcept
    : batch_(std::move(batch)),
      table_id_(table_id),
      partition_id_(partition_id),
      bucket_id_(bucket_id),
      base_offset_(base_offset) {}

bool ArrowRecordBatch::Available() const { return batch_ != nullptr; }

int64_t ArrowRecordBatch::NumRows() const {
    if (!Available()) return 0;
    return batch_->num_rows();
}

int64_t ArrowRecordBatch::GetTableId() const {
    if (!Available()) return 0;
    return this->table_id_;
}

int64_t ArrowRecordBatch::GetPartitionId() const {
    if (!Available()) return -1;
    return this->partition_id_;
}

int32_t ArrowRecordBatch::GetBucketId() const {
    if (!Available()) return -1;
    return this->bucket_id_;
}

int64_t ArrowRecordBatch::GetBaseOffset() const {
    if (!Available()) return -1;
    return this->base_offset_;
}

int64_t ArrowRecordBatch::GetLastOffset() const {
    if (!Available()) return -1;
    return this->base_offset_ + this->NumRows() - 1;
}

namespace detail {
// Imports FFI Arrow batches (C Data Interface) into C++ ArrowRecordBatch
// wrappers. A friend of ArrowRecordBatch so it can build the wrapper's private
// ctor; shared by LogScanner::PollRecordBatch and BatchScanner.
struct ArrowBatchImporter {
    static Result Import(ffi::FfiArrowRecordBatches& src, ArrowRecordBatches& out) {
        out.batches.clear();
        for (const auto& ffi_batch : src.batches) {
            auto* c_array = reinterpret_cast<struct ArrowArray*>(ffi_batch.array_ptr);
            auto* c_schema = reinterpret_cast<struct ArrowSchema*>(ffi_batch.schema_ptr);

            auto import_result = arrow::ImportRecordBatch(c_array, c_schema);
            // Free the Rust-allocated container structures whether or not the
            // import succeeded, to avoid leaks.
            ffi::free_arrow_ffi_structures(ffi_batch.array_ptr, ffi_batch.schema_ptr);
            if (!import_result.ok()) {
                return utils::make_client_error("Failed to import Arrow record batch: " +
                                                import_result.status().ToString());
            }
            out.batches.push_back(std::unique_ptr<ArrowRecordBatch>(new ArrowRecordBatch(
                import_result.ValueOrDie(), ffi_batch.table_id, ffi_batch.partition_id,
                ffi_batch.bucket_id, ffi_batch.base_offset)));
        }
        return utils::make_ok();
    }
};
}  // namespace detail

Result LogScanner::PollRecordBatch(int64_t timeout_ms, ArrowRecordBatches& out) {
    if (!Available()) {
        return utils::make_client_error("LogScanner not available");
    }

    auto ffi_result = scanner_->poll_record_batch(timeout_ms);
    auto result = utils::from_ffi_result(ffi_result.result);
    if (!result.Ok()) {
        return result;
    }
    return detail::ArrowBatchImporter::Import(ffi_result.arrow_batches, out);
}

// ============================================================================
// BatchScanner
// ============================================================================

BatchScanner::BatchScanner() noexcept = default;

BatchScanner::BatchScanner(ffi::BatchScanner* scanner) noexcept : scanner_(scanner) {}

BatchScanner::~BatchScanner() noexcept { Destroy(); }

void BatchScanner::Destroy() noexcept {
    if (scanner_) {
        ffi::delete_batch_scanner(scanner_);
        scanner_ = nullptr;
    }
}

BatchScanner::BatchScanner(BatchScanner&& other) noexcept
    : scanner_(other.scanner_), bucket_(other.bucket_) {
    other.scanner_ = nullptr;
}

BatchScanner& BatchScanner::operator=(BatchScanner&& other) noexcept {
    if (this != &other) {
        Destroy();
        scanner_ = other.scanner_;
        bucket_ = other.bucket_;
        other.scanner_ = nullptr;
    }
    return *this;
}

bool BatchScanner::Available() const { return scanner_ != nullptr; }

Result BatchScanner::NextBatch(ArrowRecordBatches& out) {
    if (!Available()) {
        return utils::make_client_error("BatchScanner not available");
    }
    auto ffi_result = scanner_->next_batch();
    auto result = utils::from_ffi_result(ffi_result.result);
    if (!result.Ok()) {
        return result;
    }
    return detail::ArrowBatchImporter::Import(ffi_result.arrow_batches, out);
}

Result BatchScanner::CollectAllBatches(ArrowRecordBatches& out) {
    if (!Available()) {
        return utils::make_client_error("BatchScanner not available");
    }
    auto ffi_result = scanner_->collect_all_batches();
    auto result = utils::from_ffi_result(ffi_result.result);
    if (!result.Ok()) {
        return result;
    }
    return detail::ArrowBatchImporter::Import(ffi_result.arrow_batches, out);
}

}  // namespace fluss
