use rayon::ThreadPool;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Chunk {
    pub data: Vec<u8>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DGGSCell {
    pub id: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Hash(pub [u8; 32]);

#[derive(Debug)]
pub struct HasherEngine {
    pub pool: Option<ThreadPool>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TransformRecord {
    pub step: String,
    pub params: serde_json::Value,
    pub in_hash: Hash,
    pub out_hash: Hash,
    pub cell: DGGSCell,
}

pub enum LogLevel {
    Error,
    Warn,
    Info,
    Debug,
}

pub fn setup_logging(level: LogLevel) {
    let lvl = match level {
        LogLevel::Error => log::LevelFilter::Error,
        LogLevel::Warn => log::LevelFilter::Warn,
        LogLevel::Info => log::LevelFilter::Info,
        LogLevel::Debug => log::LevelFilter::Debug,
    };
    let _ = env_logger::builder().filter_level(lvl).try_init();
}

pub fn handle_error(err: &dyn std::error::Error) -> String {
    err.to_string()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn setup_logging_accepts_all_levels() {
        setup_logging(LogLevel::Error);
        setup_logging(LogLevel::Warn);
        setup_logging(LogLevel::Info);
        setup_logging(LogLevel::Debug);
    }

    #[test]
    fn handle_error_returns_message() {
        let err = std::io::Error::other("boom");
        let msg = handle_error(&err);
        assert!(msg.contains("boom"));
    }
}
