mod decoder;
pub mod file;
mod index_scan_executor;
pub mod metrics;
mod types;
pub mod writer;

pub use decoder::build_sharding_key_from_import_key;
pub use types::{
    JobID as ImportJobID, JobMeta as ImportJobMeta, JobSummary as ImportJobSummary,
    Task as ImportTask, TaskID as ImportTaskID, TaskParams as ImportTaskParams,
    TaskSummary as ImportTaskSummary, TiDBImportTaskID,
};

#[cfg(test)]
mod tests {

    use std::collections::HashMap;

    use tidb_query_datatype::{
        FieldTypeTp,
        codec::{Datum, mysql, table},
        expr::EvalContext,
        prelude::*,
    };
    use tipb::ColumnInfo;

    // A simple encode and decode test using the `tidb_query_datatype` crate.
    #[test]
    fn test_encode() {
        let mut duration_col = ColumnInfo::default();
        duration_col
            .as_mut_accessor()
            .set_tp(FieldTypeTp::Duration)
            .set_decimal(2);

        let mut cols = HashMap::from_iter([
            (1, FieldTypeTp::LongLong.into()),
            (2, FieldTypeTp::VarChar.into()),
            (3, FieldTypeTp::NewDecimal.into()),
            (5, FieldTypeTp::Json.into()),
            (6, duration_col),
        ]);

        let duration_row =
            mysql::duration::Duration::parse(&mut EvalContext::default(), "23:23:23.666", 2)
                .unwrap();

        let row = HashMap::from_iter([
            (1, Datum::I64(100)),
            (2, Datum::Bytes(b"abc".to_vec())),
            (3, Datum::Dec(10.into())),
            (5, Datum::Json(r#"{"name": "John"}"#.parse().unwrap())),
            (6, Datum::Dur(duration_row)),
        ]);

        let mut ctx = EvalContext::default();
        let col_ids: Vec<_> = row.iter().map(|(&id, _)| id).collect();
        let col_values: Vec<_> = row.values().cloned().collect();

        let bs = table::encode_row(&mut ctx, col_values, &col_ids).unwrap();
        assert!(!bs.is_empty());
        assert_eq!(
            hex::encode(&bs),
            "080a0a01010000001c0000001300000004000c170000006e616d65044a6f686e08040206616263080208c801080c0880c6b69da6a52608060602008a"
        );
        let mut ctx = EvalContext::default();
        let r = table::decode_row(&mut bs.as_slice(), &mut ctx, &cols).unwrap();
        assert_eq!(row, r);

        cols.insert(4, FieldTypeTp::Float.into());
        let r = table::decode_row(&mut bs.as_slice(), &mut ctx, &cols).unwrap();
        assert_eq!(row, r);

        let bs = table::encode_row(&mut ctx, vec![], &[]).unwrap();
        assert!(!bs.is_empty());
        assert_eq!(hex::encode(&bs), "00");
        assert!(
            table::decode_row(&mut bs.as_slice(), &mut ctx, &cols)
                .unwrap()
                .is_empty()
        );
    }
}
