bitart-generator 1.0.0

Terminal pixel art generator — create art from text prompts using AI image generation
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    pub api_key: String,
    pub model: String,
    #[serde(default)]
    pub output_dir: Option<String>,
}

impl Config {
    pub fn config_dir() -> PathBuf {
        let dir = dirs::home_dir()
            .unwrap_or_else(|| PathBuf::from("."))
            .join(".bitart");
        fs::create_dir_all(&dir).ok();
        dir
    }

    pub fn config_path() -> PathBuf {
        Self::config_dir().join("config.json")
    }

    pub fn load() -> Option<Config> {
        let path = Self::config_path();
        let data = fs::read_to_string(path).ok()?;
        serde_json::from_str(&data).ok()
    }

    pub fn save(&self) -> Result<(), String> {
        let path = Self::config_path();
        let data = serde_json::to_string_pretty(self)
            .map_err(|e| format!("Failed to serialize config: {}", e))?;
        fs::write(path, data).map_err(|e| format!("Failed to write config: {}", e))
    }

    /// Build a full output path using output_dir if set, with unix timestamp filename.
    pub fn output_path(&self, ext: &str) -> String {
        let timestamp = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap_or_default()
            .as_secs();
        let filename = format!("bitart_{}.{}", timestamp, ext);
        match &self.output_dir {
            Some(dir) => {
                let path = PathBuf::from(dir).join(&filename);
                fs::create_dir_all(dir).ok();
                path.to_string_lossy().to_string()
            }
            None => filename,
        }
    }

    pub fn default_output_dir() -> String {
        dirs::download_dir()
            .or_else(dirs::home_dir)
            .unwrap_or_else(|| PathBuf::from("."))
            .join("bitart")
            .to_string_lossy()
            .to_string()
    }

    pub fn available_models() -> Vec<(&'static str, &'static str, &'static str)> {
        vec![
            ("dall-e-2", "DALL-E 2", "$0.02/image (cheapest)"),
            ("dall-e-3", "DALL-E 3", "$0.04/image"),
            ("gpt-image-1-mini", "GPT Image Mini", "$0.02/image (fast)"),
            ("gpt-image-1", "GPT Image 1", "$0.04/image"),
            ("gpt-image-1.5", "GPT Image 1.5", "$0.04/image (best quality)"),
        ]
    }
}