use std::path::PathBuf;

use directories::ProjectDirs;
use thiserror::Error;

pub struct Dirs {}

#[derive(Debug, Error)]
pub enum DirsError {
    #[error("Unable to get Project Directories")]
    ProjectDirs,
    #[error(transparent)]
    Io(#[from] std::io::Error),
    #[error(transparent)]
    Unknown(#[from] anyhow::Error),
}

impl Dirs {
    pub fn get_config_dir() -> Result<PathBuf, DirsError> {
        let Some(proj_dirs) = ProjectDirs::from("nl", "Avii", "Avam") else {
            return Err(DirsError::ProjectDirs);
        };

        let config_dir = proj_dirs.config_local_dir();

        if !config_dir.exists() {
            std::fs::create_dir_all(config_dir)?;
        }
        Ok(config_dir.to_path_buf())
    }

    pub fn get_config_file() -> Result<PathBuf, DirsError> {
        let mut c = Self::get_config_dir()?;
        c.push("config.toml");
        Ok(c)
    }

    pub fn get_lock_file() -> Result<PathBuf, DirsError> {
        let mut c = Self::get_config_dir()?;
        c.push(".lock");
        Ok(c)
    }

    #[cfg(not(debug_assertions))]
    pub fn get_log_dir() -> Result<PathBuf, DirsError> {
        let c = Self::get_config_dir()?;
        let mut log_dir = c.parent().unwrap().to_path_buf();
        log_dir.push("logs");
        if !log_dir.exists() {
            std::fs::create_dir_all(&log_dir)?;
        }

        Ok(log_dir.to_path_buf())
    }

    #[cfg(not(debug_assertions))]
    pub fn get_log_file() -> Result<PathBuf, DirsError> {
        let mut l = Self::get_log_dir()?;
        l.push("avam.log");
        Ok(l)
    }
}
