/*
 * 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 "paimon/format/parquet/file_reader_wrapper.h"

#include <algorithm>
#include <cassert>
#include <cstddef>

#include "arrow/io/interfaces.h"
#include "arrow/record_batch.h"
#include "arrow/util/range.h"
#include "fmt/format.h"
#include "paimon/common/utils/arrow/arrow_utils.h"
#include "paimon/format/parquet/column_index_filter.h"
#include "paimon/format/parquet/page_filtered_row_group_reader.h"
#include "paimon/format/parquet/parquet_format_defs.h"
#include "paimon/macros.h"
#include "parquet/arrow/reader.h"
#include "parquet/arrow/schema.h"
#include "parquet/file_reader.h"
#include "parquet/metadata.h"
#include "parquet/page_index.h"

namespace paimon::parquet {

namespace {

// Merge overlapping or adjacent ReadRanges into a minimal set of non-overlapping ranges.
// PreBufferRanges requires non-overlapping ranges, so this is necessary when combining
// ranges from multiple sources (page-level ranges, column chunk ranges, etc.).
std::vector<::arrow::io::ReadRange> MergeOverlappingRanges(
    std::vector<::arrow::io::ReadRange> ranges) {
    if (ranges.empty()) {
        return ranges;
    }

    // Sort by offset
    std::sort(ranges.begin(), ranges.end(),
              [](const ::arrow::io::ReadRange& a, const ::arrow::io::ReadRange& b) {
                  return a.offset < b.offset;
              });

    std::vector<::arrow::io::ReadRange> merged;
    merged.push_back(ranges[0]);

    for (size_t i = 1; i < ranges.size(); ++i) {
        auto& last = merged.back();
        const auto& curr = ranges[i];
        // Check if current range overlaps or is adjacent to the last merged range
        int64_t last_end = last.offset + last.length;
        if (curr.offset <= last_end) {
            // Merge: extend the last range if current extends beyond it
            int64_t curr_end = curr.offset + curr.length;
            if (curr_end > last_end) {
                last.length = curr_end - last.offset;
            }
        } else {
            // No overlap, add as new range
            merged.push_back(curr);
        }
    }

    return merged;
}

}  // namespace

Result<std::unique_ptr<FileReaderWrapper>> FileReaderWrapper::Create(
    std::unique_ptr<::parquet::arrow::FileReader>&& file_reader, int64_t batch_size,
    std::shared_ptr<::arrow::MemoryPool> pool) {
    try {
        if (file_reader == nullptr) {
            return Status::Invalid("file reader wrapper create failed. file reader is nullptr");
        }
        std::vector<std::pair<uint64_t, uint64_t>> all_row_group_ranges;
        auto meta_data = file_reader->parquet_reader()->metadata();
        // prepare [start_row_idx, end_row_idx) for all row groups
        uint64_t start_row_idx = 0;
        for (int32_t i = 0; i < meta_data->num_row_groups(); i++) {
            uint64_t end_row_idx = start_row_idx + meta_data->RowGroup(i)->num_rows();
            all_row_group_ranges.emplace_back(start_row_idx, end_row_idx);
            start_row_idx = end_row_idx;
        }
        uint64_t num_rows = file_reader->parquet_reader()->metadata()->num_rows();
        if (start_row_idx != num_rows) {
            assert(false);
            return Status::Invalid(fmt::format(
                "unexpected error. row group ranges not match with num rows {}", num_rows));
        }
        std::vector<int32_t> columns_indices =
            arrow::internal::Iota(file_reader->parquet_reader()->metadata()->num_columns());
        auto file_reader_wrapper = std::unique_ptr<FileReaderWrapper>(new FileReaderWrapper(
            std::move(file_reader), all_row_group_ranges, num_rows, batch_size, pool));
        std::vector<TargetRowGroup> all_target_row_groups;
        for (int32_t i = 0; i < file_reader_wrapper->GetNumberOfRowGroups(); i++) {
            all_target_row_groups.emplace_back(/*rg_index=*/i, /*is_partially_matched=*/false,
                                               /*ranges=*/RowRanges());
        }
        PAIMON_RETURN_NOT_OK(
            file_reader_wrapper->PrepareForReadingLazy(all_target_row_groups, columns_indices));
        return file_reader_wrapper;
    }
    PAIMON_PARQUET_CATCH_AND_RETURN_STATUS("FileReaderWrapper::Create")
}

FileReaderWrapper::~FileReaderWrapper() {
    WaitForPendingPreBuffer();
}

Result<std::shared_ptr<arrow::Schema>> FileReaderWrapper::GetSchema() const {
    try {
        std::shared_ptr<arrow::Schema> file_schema;
        PAIMON_RETURN_NOT_OK_FROM_ARROW(file_reader_->GetSchema(&file_schema));
        return file_schema;
    }
    PAIMON_PARQUET_CATCH_AND_RETURN_STATUS("FileReaderWrapper::GetSchema")
}

Status FileReaderWrapper::Close() {
    try {
        if (batch_reader_) {
            PAIMON_RETURN_NOT_OK_FROM_ARROW(batch_reader_->Close());
        }
        return Status::OK();
    }
    PAIMON_PARQUET_CATCH_AND_RETURN_STATUS("FileReaderWrapper::Close")
}

FileReaderWrapper::FileReaderWrapper(
    std::unique_ptr<::parquet::arrow::FileReader>&& file_reader,
    const std::vector<std::pair<uint64_t, uint64_t>>& all_row_group_ranges, uint64_t num_rows,
    int64_t batch_size, std::shared_ptr<::arrow::MemoryPool> pool)
    : file_reader_(std::move(file_reader)),
      all_row_group_ranges_(all_row_group_ranges),
      pool_(std::move(pool)),
      batch_size_(batch_size),
      num_rows_(num_rows) {}

void FileReaderWrapper::WaitForPendingPreBuffer() {
    if (!prebuffered_ranges_.empty() && file_reader_) {
        // Wait for all outstanding PreBuffer async reads to complete before destruction.
        // Without this, JindoSDK async pread callbacks may fire after the underlying
        // buffers and memory pool are freed, causing use-after-free crashes.
        auto status =
            file_reader_->parquet_reader()->WhenBufferedRanges(prebuffered_ranges_).status();
        (void)status;  // Best-effort; ignore errors during cleanup
        prebuffered_ranges_.clear();
    }
}

void FileReaderWrapper::AdvanceToNextRowGroup() {
    current_row_group_idx_++;
    // Skip row groups excluded by read range.
    while (current_row_group_idx_ < target_row_groups_.size() &&
           target_row_groups_[current_row_group_idx_].IsExcludedByReadRange()) {
        current_row_group_idx_++;
    }
    if (current_row_group_idx_ >= target_row_groups_.size()) {
        next_row_to_read_ = num_rows_;
    } else {
        next_row_to_read_ =
            all_row_group_ranges_[target_row_groups_[current_row_group_idx_].GetRowGroupIndex()]
                .first;
    }
}

Status FileReaderWrapper::SeekToRow(uint64_t row_number) {
    try {
        current_page_filtered_reader_.reset();
        filtered_global_offset_ = 0;

        for (uint64_t i = 0; i < target_row_groups_.size(); i++) {
            if (target_row_groups_[i].IsExcludedByReadRange()) {
                continue;
            }
            int32_t rg_id = target_row_groups_[i].GetRowGroupIndex();
            uint64_t rg_start = all_row_group_ranges_[rg_id].first;
            uint64_t rg_end = all_row_group_ranges_[rg_id].second;
            if (row_number > rg_start && row_number < rg_end) {
                return Status::Invalid(
                    fmt::format("seek to row failed. row number {} should not be in the middle of "
                                "readable range",
                                row_number));
            }
            if (rg_start >= row_number) {
                current_row_group_idx_ = i;
                next_row_to_read_ = rg_start;

                // Rebuild batch_reader_ for non-page-filtered RGs at/after seek position.
                std::vector<int32_t> fully_matched_indices;
                for (uint64_t j = i; j < target_row_groups_.size(); j++) {
                    if (!target_row_groups_[j].IsExcludedByReadRange() &&
                        !target_row_groups_[j].IsPartiallyMatched()) {
                        fully_matched_indices.push_back(target_row_groups_[j].GetRowGroupIndex());
                    }
                }
                if (!fully_matched_indices.empty()) {
                    PAIMON_RETURN_NOT_OK_FROM_ARROW(file_reader_->GetRecordBatchReader(
                        fully_matched_indices, target_column_indices_, &batch_reader_));
                } else {
                    batch_reader_.reset();
                }
                return Status::OK();
            }
        }
        next_row_to_read_ = num_rows_;
        current_row_group_idx_ = target_row_groups_.size();
        return Status::OK();
    }
    PAIMON_PARQUET_CATCH_AND_RETURN_STATUS("FileReaderWrapper::SeekToRow")
}

Result<std::shared_ptr<arrow::RecordBatch>> FileReaderWrapper::NextPageFiltered() {
    int32_t rg_id = target_row_groups_[current_row_group_idx_].GetRowGroupIndex();

    // Construct the per-RG streaming reader on demand.
    if (!current_page_filtered_reader_) {
        const auto& target_rg = target_row_groups_[current_row_group_idx_];
        auto row_group_page_index_reader = GetRowGroupPageIndexReader(rg_id);
        auto page_ranges = PageFilteredRowGroupReader::ComputePageRanges(
            target_rg, target_column_indices_, row_group_page_index_reader,
            file_reader_->parquet_reader());
        bool pre_buffered = !prebuffered_ranges_.empty();
        int64_t max_chunksize = batch_size_ > 0 ? batch_size_ : std::numeric_limits<int64_t>::max();
        PAIMON_ASSIGN_OR_RAISE(
            current_page_filtered_reader_,
            PageFilteredRowGroupReader::ReadFilteredRowGroup(
                target_rg, target_column_indices_, file_reader_->properties().cache_options(),
                pre_buffered, page_ranges, max_chunksize, row_group_page_index_reader, pool_,
                file_reader_.get()));
        current_filtered_row_ranges_ = target_rg.GetRowRanges();
        current_filtered_rg_start_ = all_row_group_ranges_[rg_id].first;
        filtered_global_offset_ = 0;
    }

    std::shared_ptr<arrow::RecordBatch> record_batch;
    PAIMON_RETURN_NOT_OK_FROM_ARROW(current_page_filtered_reader_->ReadNext(&record_batch));

    if (record_batch) {
        auto original_row =
            current_filtered_row_ranges_.MapFilteredIndexToOriginalRow(filtered_global_offset_);
        previous_first_row_ = original_row.has_value() ? current_filtered_rg_start_ +
                                                             static_cast<uint64_t>(*original_row)
                                                       : current_filtered_rg_start_;
        filtered_global_offset_ += record_batch->num_rows();
        // Advance to the next row that survives filtering, or to the row group end when the
        // filtered ranges are exhausted, so that next_row_to_read_ tracks the streaming position.
        auto next_original_row =
            current_filtered_row_ranges_.MapFilteredIndexToOriginalRow(filtered_global_offset_);
        next_row_to_read_ =
            next_original_row.has_value()
                ? current_filtered_rg_start_ + static_cast<uint64_t>(*next_original_row)
                : all_row_group_ranges_[rg_id].second;
        return record_batch;
    }

    // RG exhausted — reset and advance.
    current_page_filtered_reader_.reset();
    filtered_global_offset_ = 0;
    AdvanceToNextRowGroup();
    return std::shared_ptr<arrow::RecordBatch>();
}

Result<std::shared_ptr<arrow::RecordBatch>> FileReaderWrapper::NextFullyMatched() {
    if (!batch_reader_) {
        return std::shared_ptr<arrow::RecordBatch>();
    }

    PAIMON_ASSIGN_OR_RAISE_FROM_ARROW(std::shared_ptr<arrow::RecordBatch> record_batch,
                                      batch_reader_->Next());
    if (!record_batch) {
        return std::shared_ptr<arrow::RecordBatch>();
    }
    // Large binary columns (exceed 2GB) may split at different row boundaries. TableBatchReader
    // aligns their chunks by slicing columns, which may leave non-zero child offsets.
    PAIMON_ASSIGN_OR_RAISE(record_batch,
                           ArrowUtils::NormalizeRecordBatchOffsets(record_batch, pool_.get()));

    int32_t rg_id = target_row_groups_[current_row_group_idx_].GetRowGroupIndex();
    uint64_t rg_end = all_row_group_ranges_[rg_id].second;
    int64_t num_rows = record_batch->num_rows();

    previous_first_row_ = next_row_to_read_;
    if (next_row_to_read_ + num_rows < rg_end) {
        next_row_to_read_ += num_rows;
    } else if (next_row_to_read_ + num_rows == rg_end) {
        AdvanceToNextRowGroup();
    } else {
        return Status::Invalid(
            fmt::format("Next failed. next_row_to_read {} + num_rows {} exceeds row group end {}",
                        next_row_to_read_, num_rows, rg_end));
    }
    return record_batch;
}

std::shared_ptr<::parquet::RowGroupPageIndexReader> FileReaderWrapper::GetRowGroupPageIndexReader(
    int32_t row_group_index) {
    auto cached = row_group_page_index_readers_.find(row_group_index);
    if (cached != row_group_page_index_readers_.end()) {
        return cached->second;
    }

    std::shared_ptr<::parquet::RowGroupPageIndexReader> row_group_page_index_reader;
    auto page_index_reader = GetPageIndexReader();
    if (page_index_reader) {
        row_group_page_index_reader = page_index_reader->RowGroup(row_group_index);
    }

    // To avoid OOM, limit the number of row group page index readers cached in memory.
    constexpr int32_t kMaxRowGroupPageIndexReaders = 1024;
    if (row_group_page_index_readers_.size() < kMaxRowGroupPageIndexReaders) {
        row_group_page_index_readers_.emplace(row_group_index, row_group_page_index_reader);
    }
    return row_group_page_index_reader;
}

Result<std::shared_ptr<arrow::RecordBatch>> FileReaderWrapper::Next() {
    try {
        if (PAIMON_UNLIKELY(!reader_initialized_)) {
            PAIMON_RETURN_NOT_OK(PrepareForReading(target_row_groups_, target_column_indices_));
        }

        while (current_row_group_idx_ < target_row_groups_.size()) {
            bool is_partially_matched =
                target_row_groups_[current_row_group_idx_].IsPartiallyMatched();
            PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<arrow::RecordBatch> batch,
                                   is_partially_matched ? NextPageFiltered() : NextFullyMatched());
            if (batch) {
                return batch;
            } else if (!is_partially_matched) {
                // Null from fully-matched path means batch_reader_ is globally exhausted.
                break;
            }
            // current_row_group_idx_ has been advanced in NextPageFiltered() or NextFullyMatched(),
            // loop to try next RG.
        }

        previous_first_row_ = next_row_to_read_;
        return std::shared_ptr<arrow::RecordBatch>();
    }
    PAIMON_PARQUET_CATCH_AND_RETURN_STATUS("FileReaderWrapper::Next")
}

Result<std::vector<std::pair<uint64_t, uint64_t>>> FileReaderWrapper::GetRowGroupRanges(
    const std::set<int32_t>& row_group_indices) const {
    std::vector<std::pair<uint64_t, uint64_t>> row_group_ranges;
    for (auto row_group_index : row_group_indices) {
        if (static_cast<size_t>(row_group_index) >= all_row_group_ranges_.size()) {
            return Status::Invalid(fmt::format("row group index {} is out of bound {}",
                                               row_group_index, all_row_group_ranges_.size()));
        }
        row_group_ranges.push_back(all_row_group_ranges_[row_group_index]);
    }
    return row_group_ranges;
}

Status FileReaderWrapper::PrepareForReadingLazy(
    const std::vector<TargetRowGroup>& target_row_groups,
    const std::vector<int32_t>& column_indices) {
    target_row_groups_ = target_row_groups;
    target_column_indices_ = column_indices;
    reader_initialized_ = false;
    return Status::OK();
}

std::vector<::arrow::io::ReadRange> FileReaderWrapper::CollectPreBufferRanges(
    const std::vector<int32_t>& column_indices) {
    std::vector<::arrow::io::ReadRange> ranges;
    auto file_metadata = file_reader_->parquet_reader()->metadata();

    for (const auto& trg : target_row_groups_) {
        if (trg.IsExcludedByReadRange()) continue;

        if (trg.IsPartiallyMatched()) {
            // Page-filtered RGs: only matching page byte ranges.
            auto row_group_page_index_reader = GetRowGroupPageIndexReader(trg.GetRowGroupIndex());
            auto page_ranges = PageFilteredRowGroupReader::ComputePageRanges(
                trg, column_indices, row_group_page_index_reader, file_reader_->parquet_reader());
            ranges.insert(ranges.end(), std::make_move_iterator(page_ranges.begin()),
                          std::make_move_iterator(page_ranges.end()));
        } else {
            // Fully-matched RGs: entire column chunk ranges.
            auto rg_metadata = file_metadata->RowGroup(trg.GetRowGroupIndex());
            for (int32_t col_idx : column_indices) {
                auto col_chunk = rg_metadata->ColumnChunk(col_idx);
                int64_t offset = col_chunk->data_page_offset();
                if (col_chunk->has_dictionary_page() && col_chunk->dictionary_page_offset() > 0 &&
                    offset > col_chunk->dictionary_page_offset()) {
                    offset = col_chunk->dictionary_page_offset();
                }
                ranges.push_back({offset, col_chunk->total_compressed_size()});
            }
        }
    }
    return ranges;
}

void FileReaderWrapper::DispatchPreBuffer(std::vector<::arrow::io::ReadRange> ranges) {
    const auto& cache_opts = file_reader_->properties().cache_options();
    ::arrow::io::IOContext io_ctx(pool_.get());
    auto merged_ranges = MergeOverlappingRanges(std::move(ranges));
    try {
        file_reader_->parquet_reader()->PreBufferRanges(merged_ranges, io_ctx, cache_opts);
        prebuffered_ranges_ = std::move(merged_ranges);
    } catch (const std::exception&) {
        prebuffered_ranges_.clear();
    }
}

Status FileReaderWrapper::PrepareForReading(const std::vector<TargetRowGroup>& target_row_groups,
                                            const std::vector<int32_t>& column_indices) {
    try {
        target_row_groups_ = target_row_groups;
        target_column_indices_ = column_indices;

        // Partition into fully-matched and page-filtered row groups, skipping excluded ones.
        std::vector<int32_t> fully_matched_row_groups;
        uint64_t active_count = 0;
        for (const auto& trg : target_row_groups_) {
            if (trg.IsExcludedByReadRange()) {
                continue;
            }
            active_count++;
            if (!trg.IsPartiallyMatched()) {
                fully_matched_row_groups.push_back(trg.GetRowGroupIndex());
            }
        }

        bool has_partially_matched = fully_matched_row_groups.size() != active_count;

        WaitForPendingPreBuffer();

        // TODO(Yonghao Fang): Neither Paimon nor Arrow manage the size and lifecycle of prebuffered
        // caches. So when a lot of row is needed, there is possibility of OOM due to too much
        // prebuffering. Also, DispatchPreBuffer will drop previous prebuffered ranges by
        // GetRecordBatchReader, which cause IO wastes.

        // Create standard reader for fully-matched row groups.
        if (!fully_matched_row_groups.empty()) {
            PAIMON_RETURN_NOT_OK_FROM_ARROW(file_reader_->GetRecordBatchReader(
                fully_matched_row_groups, column_indices, &batch_reader_));
        } else {
            batch_reader_.reset();
        }

        // When page-filtered RGs exist, issue a single PreBuffer covering both kinds.
        // Otherwise GetRecordBatchReader already issued PreBuffer internally.
        if (has_partially_matched) {
            auto all_ranges = CollectPreBufferRanges(column_indices);
            DispatchPreBuffer(std::move(all_ranges));
        }

        // Reset read state. Find the first non-excluded row group.
        uint64_t first_active_idx = 0;
        while (first_active_idx < target_row_groups_.size() &&
               target_row_groups_[first_active_idx].IsExcludedByReadRange()) {
            first_active_idx++;
        }
        if (first_active_idx >= target_row_groups_.size()) {
            next_row_to_read_ = num_rows_;
        } else {
            next_row_to_read_ =
                all_row_group_ranges_[target_row_groups_[first_active_idx].GetRowGroupIndex()]
                    .first;
        }
        previous_first_row_ = std::numeric_limits<uint64_t>::max();
        current_row_group_idx_ = first_active_idx;
        reader_initialized_ = true;
        return Status::OK();
    }
    PAIMON_PARQUET_CATCH_AND_RETURN_STATUS("FileReaderWrapper::PrepareForReading")
}

Status FileReaderWrapper::ApplyReadRanges(
    const std::vector<std::pair<uint64_t, uint64_t>>& read_ranges) {
    if (read_ranges.empty()) {
        for (auto& trg : target_row_groups_) {
            trg.SetExcludedByReadRange(true);
        }
        reader_initialized_ = false;
        return Status::OK();
    }
    // Build a set of row group indices whose range matches one of the read ranges.
    std::set<int32_t> matching_rg_indices;
    for (const auto& read_range : read_ranges) {
        for (size_t i = 0; i < all_row_group_ranges_.size(); i++) {
            if (all_row_group_ranges_[i] == read_range) {
                matching_rg_indices.insert(static_cast<int32_t>(i));
            }
        }
    }
    // Mark each target row group as excluded or not based on the matching set.
    for (auto& trg : target_row_groups_) {
        trg.SetExcludedByReadRange(matching_rg_indices.count(trg.GetRowGroupIndex()) == 0);
    }
    reader_initialized_ = false;
    return Status::OK();
}

std::shared_ptr<::parquet::PageIndexReader> FileReaderWrapper::GetPageIndexReader() {
    try {
        return file_reader_->parquet_reader()->GetPageIndexReader();
    } catch (...) {
        // Page index is optional; degrade gracefully if the metadata read throws.
        return nullptr;
    }
}

Result<RowRanges> FileReaderWrapper::CalculateFilteredRowRanges(
    int32_t row_group_index, const std::shared_ptr<Predicate>& predicate,
    const std::map<std::string, int32_t>& column_name_to_index) {
    try {
        auto meta_data = file_reader_->parquet_reader()->metadata();
        int64_t row_count = meta_data->RowGroup(row_group_index)->num_rows();

        if (!predicate) {
            return RowRanges::CreateSingle(row_count);
        }

        return ColumnIndexFilter::CalculateRowRanges(predicate,
                                                     GetRowGroupPageIndexReader(row_group_index),
                                                     column_name_to_index, row_count);
    }
    PAIMON_PARQUET_CATCH_AND_RETURN_STATUS("FileReaderWrapper::CalculateFilteredRowRanges")
}

}  // namespace paimon::parquet
