use std::path::{Path, PathBuf};
use std::fs;

/// Central configuration for all data paths
pub struct DataPaths {
  base_dir: PathBuf,
  data_dir: PathBuf,
  cache_dir: PathBuf,
  logs_dir: PathBuf,
  // Economic data subdirectories
  economic_events_dir: PathBuf,
  economic_changes_dir: PathBuf,
  // Corporate data subdirectories
  corporate_events_dir: PathBuf,
  corporate_changes_dir: PathBuf,
  corporate_prices_dir: PathBuf,
}

impl DataPaths {
  /// Initialize paths from a base directory
  pub fn new(base_dir: impl AsRef<Path>) -> std::io::Result<Self> {
    let base_dir = base_dir.as_ref().to_path_buf();
    
    let data_dir = base_dir.join("data");
    let cache_dir = base_dir.join("cache");
    let logs_dir = base_dir.join("logs");
    
    // Economic subdirectories
    let economic_events_dir = data_dir.join("economic").join("events");
    let economic_changes_dir = economic_events_dir.join("changes");
    
    // Corporate subdirectories
    let corporate_dir = data_dir.join("corporate");
    let corporate_events_dir = corporate_dir.join("events");
    let corporate_changes_dir = corporate_events_dir.join("changes");
    let corporate_prices_dir = corporate_dir.join("prices");
    
    // Create all directories if they don't exist
    fs::create_dir_all(&data_dir)?;
    fs::create_dir_all(&cache_dir)?;
    fs::create_dir_all(&logs_dir)?;
    fs::create_dir_all(&economic_events_dir)?;
    fs::create_dir_all(&economic_changes_dir)?;
    fs::create_dir_all(&corporate_events_dir)?;
    fs::create_dir_all(&corporate_changes_dir)?;
    fs::create_dir_all(&corporate_prices_dir)?;
    
    Ok(Self {
      base_dir,
      data_dir,
      cache_dir,
      logs_dir,
      economic_events_dir,
      economic_changes_dir,
      corporate_events_dir,
      corporate_changes_dir,
      corporate_prices_dir,
    })
  }
  
  pub fn base_dir(&self) -> &Path {
    &self.base_dir
  }
  
  pub fn data_dir(&self) -> &Path {
    &self.data_dir
  }
  
  pub fn cache_dir(&self) -> &Path {
    &self.cache_dir
  }
  
  pub fn logs_dir(&self) -> &Path {
    &self.logs_dir
  }
  
  /// Get the economic events directory
  pub fn economic_events_dir(&self) -> &Path {
    &self.economic_events_dir
  }
  
  /// Get the economic changes directory
  pub fn economic_changes_dir(&self) -> &Path {
    &self.economic_changes_dir
  }
  
  /// Get the corporate events directory
  pub fn corporate_events_dir(&self) -> &Path {
    &self.corporate_events_dir
  }
  
  /// Get the corporate changes directory
  pub fn corporate_changes_dir(&self) -> &Path {
    &self.corporate_changes_dir
  }
  
  /// Get the corporate prices directory
  pub fn corporate_prices_dir(&self) -> &Path {
    &self.corporate_prices_dir
  }
  
  /// Get a specific file path within data directory
  pub fn data_file(&self, filename: &str) -> PathBuf {
    self.data_dir.join(filename)
  }
  
  /// Get a specific file path within cache directory
  pub fn cache_file(&self, filename: &str) -> PathBuf {
    self.cache_dir.join(filename)
  }
  
  /// Get a specific file path within logs directory
  pub fn log_file(&self, filename: &str) -> PathBuf {
    self.logs_dir.join(filename)
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  
  #[test]
  fn test_paths_creation() {
    let paths = DataPaths::new("./test_base").unwrap();
    assert!(paths.data_dir().exists());
    assert!(paths.cache_dir().exists());
    assert!(paths.logs_dir().exists());
    assert!(paths.economic_events_dir().exists());
    assert!(paths.economic_changes_dir().exists());
    assert!(paths.corporate_events_dir().exists());
    assert!(paths.corporate_changes_dir().exists());
    assert!(paths.corporate_prices_dir().exists());
  }
}