use std::{error::Error, sync::Arc};

use tici_shard::reader::{
    query_info::QueryInfo,
    query_result::SearchRows,
    shard_reader::{ShardReader, ShardReaderStat},
};

use crate::ffi::SearchResult;

impl From<SearchRows> for SearchResult {
    fn from(rows: SearchRows) -> Self {
        Self {
            row_count: rows.row_count,
            i64_columns: rows
                .i64_columns
                .into_iter()
                .map(|column| crate::ffi::I64ColumnData {
                    col_name: column.col_name,
                    values: column.values,
                    null_map: column.null_map,
                })
                .collect(),
            u64_columns: rows
                .u64_columns
                .into_iter()
                .map(|column| crate::ffi::U64ColumnData {
                    col_name: column.col_name,
                    values: column.values,
                    null_map: column.null_map,
                })
                .collect(),
            f64_columns: rows
                .f64_columns
                .into_iter()
                .map(|column| crate::ffi::F64ColumnData {
                    col_name: column.col_name,
                    values: column.values,
                    null_map: column.null_map,
                })
                .collect(),
            bytes_columns: rows
                .bytes_columns
                .into_iter()
                .map(|column| crate::ffi::BytesColumnData {
                    col_name: column.col_name,
                    chars: column.chars,
                    offsets: column.offsets,
                    null_map: column.null_map,
                })
                .collect(),
        }
    }
}

pub fn search_shard_reader(
    shard_reader: &ShardReader,
    query_info: Arc<QueryInfo>,
) -> Result<(SearchResult, ShardReaderStat), Box<dyn Error>> {
    let (res, search_stat) = shard_reader.search_with_query_info(query_info)?;
    let search_result = res.into();
    Ok((search_result, search_stat))
}
