use std::{
   fs,
   collections::HashMap,
};
use serde::{Deserialize,Serialize};

use crate::defs::{
  UserRole,
  user_role::deserialize_user_role,
};

use log::{info,error};

use crate::FILE_SCHEME;

#[derive(Deserialize,Serialize,Clone,Debug,Default)]
pub struct Authz {
  pub user_id: String,
  pub name: String,
  pub passwd: String,
  pub init: String,
  pub last: String,
  pub change: bool,
    #[serde(deserialize_with = "deserialize_user_role")]
  pub role: UserRole,
}

// pub type AuthzMap = Arc<RwLock<HashMap<String,Authz>>>;
#[derive(Clone,Debug)]
pub struct AuthStore {
  pub authz: HashMap<String,Authz>,
  // pub authz: AuthzMap,
} 
impl AuthStore {
  pub fn new(authz_store_uri: &str) -> Self {
    Self {
      authz: AuthStore::create_authz_map(authz_store_uri),
//      authz: Arc::new(RwLock::new(AuthStore::create_authz_map(config))),
    }
  }
  pub fn load_authz_from_fs(target: &str) -> HashMap<String, Authz> {
    let data_content = fs::read_to_string(target).unwrap_or_else(|_|String::from(""));
    if ! data_content.contains("role") {
      println!("Error no 'role' in authz from store: {}", &target);
      return HashMap::new()
    } 
    let authz: HashMap<String, Authz> = toml::from_str(&data_content).unwrap_or_else(|e| {
        println!("Error loading authz from store: {} error: {}", &target,e);
        HashMap::new()
    });
    authz
  }

  pub fn create_authz_map(authz_store_uri: &str) -> HashMap<String, Authz> {
    let mut authz = HashMap::new();
    if authz_store_uri.starts_with(FILE_SCHEME) {
        let authz_store = authz_store_uri.replace(FILE_SCHEME, "");
        authz = AuthStore::load_authz_from_fs(&authz_store);
        if !authz.is_empty() { 
          info!("Authz loaded successfully ({})", &authz.len());
        }
    } else {
        error!("Store not set for authz store: {}", authz_store_uri);
    }
    authz
  }
}
