use anyhow::{Context, Result};
use tantivy::{Index, IndexWriter};
use tici_common::index::IndexKey;

pub mod batch_queue;
pub mod cmp_doc;
pub mod dedup_bitset;
pub mod frag_path_generator;
pub mod key;
pub mod meta_client;
pub mod meta_client_pool;
pub mod metrics;
pub mod row_entry;
pub mod s3_frag;
pub mod schema;
pub mod tantivy_doc;

pub fn frag_index_path(frag_path: &str) -> String {
    format!("{}/index", frag_path)
}

pub const FRAG_ROW_ENTRY_FILE: &str = "row_entry.parquet";

pub fn frag_row_entry_path(frag_path: &str) -> String {
    format!("{}/{}", frag_path, FRAG_ROW_ENTRY_FILE)
}

pub fn frag_index_meta_path(frag_path: &str) -> String {
    format!("{}/{}", frag_path, s3_frag::FRAG_INDEX_META_FILE)
}

pub fn frag_multi_path(frag_path: &str, i: u32) -> String {
    format!("{}/multi.{}", frag_path, i)
}

// For logging and debugging
pub fn shard_tracing_id(index_key: &IndexKey, shard_id: u64) -> String {
    if index_key.is_tidb_x() {
        format!(
            "ks_{}/t_{}/i_{}/s_{}",
            index_key.keyspace_id, index_key.table_id, index_key.index_id, shard_id
        )
    } else {
        format!(
            "t_{}/i_{}/s_{}",
            index_key.table_id, index_key.index_id, shard_id
        )
    }
}

// For logging and debugging
pub fn import_task_tracing_id(task_id: u64) -> String {
    format!("task_id={}", task_id)
}

pub fn build_info() -> String {
    // profile.release.debug is true in Cargo.toml, so
    // VERGEN_CARGO_DEBUG will always be true.
    let build_mode = if cfg!(debug_assertions) {
        "debug"
    } else {
        "release"
    };
    format!(
        "build_time={} commit={} build={}(opt={}) rustc={}",
        env!("VERGEN_BUILD_TIMESTAMP").split('.').next().unwrap(),
        env!("VERGEN_GIT_SHA"),
        build_mode,
        env!("VERGEN_CARGO_OPT_LEVEL"),
        env!("VERGEN_RUSTC_SEMVER")
    )
}

pub fn create_index_writer(
    index: &Index,
    index_num_threads: usize,
    index_mem_budget: usize,
    frag_path: &str,
) -> Result<IndexWriter> {
    let index_writer = index
        .writer_with_num_threads(index_num_threads, index_mem_budget)
        .with_context(|| format!("create_index_writer failed. frag_path={}", frag_path))?;
    index_writer.set_merge_policy(Box::new(tantivy::merge_policy::NoMergePolicy));
    Ok(index_writer)
}
