use crate::cache::{get_hash, get_str, BB8Pool, CacheError};
use crate::get_hash_all_values;
use cal_core::Region;
use log::{debug, info};
use std::collections::HashMap;

pub async fn get_regions(pool: &BB8Pool) -> Result<HashMap<String, Region>, CacheError> {
    let mut regions = HashMap::<String, Region>::new();
    let result = get_hash_all_values(pool, "cb:regions").await?;
    for id in result.values() {
        if (regions.get(id).is_none()) {
            let region = get_region_by_id(pool, id).await?;
            if region.is_some() {
                regions.insert(id.to_string(), region.unwrap());
            }
        }
    }
    Ok(regions)
}

pub async fn get_region_by_ident(
    pool: &BB8Pool,
    key: &str,
) -> Result<Option<Region>, CacheError> {
    let result = get_hash(pool, "cb:regions", key).await;
    match result {
        Ok(r) => match r {
            None => {
                info!("get_region_by_ident_lite({}) Redis Result None", key);
                Ok(None)
            }
            Some(value) => {
                //HASH values created by Java Redisson have unwanted " in value so remove them
                let fixed_str = value.replace("\"", "");
                debug!(
                    "get_region_by_ident_lite({}) Redis Result {}",
                    &key, &fixed_str
                );
                get_region_by_id(pool, fixed_str.as_str()).await
            }
        },
        Err(e) => Err(e),
    }
}

pub async fn get_region_by_id(
    pool: &BB8Pool,
    key: &str,
) -> Result<Option<Region>, CacheError> {
    let _key = format!("cb:region:{}", key);
    let result = get_str(pool, &_key).await;
    match result {
        Ok(r) => match r {
            None => {
                info!("get_region_by_id_lite({}) Redis Result None", &_key);
                Ok(None)
            }
            Some(value) => {
                let region: Region = serde_json::from_str(&value).unwrap();
                debug!(
                    "get_region_by_id_lite({}) Redis Result {}",
                    &_key, region.name
                );
                Ok(Some(region))
            }
        },
        Err(e) => Err(e),
    }
}
