//! Configuration utilities for shared use
//!
//! This module provides configuration loading and management utilities
//! that are shared between client and server crates.

use serde::{Deserialize, Serialize};
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ConfigError {
    #[error("Configuration file not found: {0}")]
    FileNotFound(String),
    #[error("Configuration parsing error: {0}")]
    ParseError(String),
    #[error("Missing required configuration: {0}")]
    MissingConfig(String),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppConfig {
    pub app: AppSection,
    pub server: ServerSection,
    pub content: ContentSection,
    pub routing: RoutingSection,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppSection {
    pub name: String,
    pub version: String,
    pub environment: String,
    #[serde(default)]
    pub debug: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerSection {
    pub host: String,
    pub port: u16,
    #[serde(default = "default_workers")]
    pub workers: usize,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContentSection {
    pub root_path: String,
    pub public_path: String,
    pub content_url: String,
    pub types: Vec<String>,
    pub languages: Vec<String>,
    pub default_language: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RoutingSection {
    pub routes_source: String,
    pub i18n_source: String,
    pub generation_mode: String,
    #[serde(default)]
    pub watch_changes: bool,
}

fn default_workers() -> usize {
    1
}

impl AppConfig {
    pub fn load_from_file(path: &str) -> Result<Self, ConfigError> {
        let content = std::fs::read_to_string(path).map_err(|err| match err.kind() {
            std::io::ErrorKind::NotFound => ConfigError::FileNotFound(path.to_string()),
            std::io::ErrorKind::PermissionDenied => {
                ConfigError::FileNotFound(format!("Permission denied: {}", path))
            }
            other => ConfigError::FileNotFound(format!("{}: {}", path, other)),
        })?;

        toml::from_str(&content).map_err(|e| {
            ConfigError::ParseError(format!("Failed to parse config at {}: {}", path, e))
        })
    }

    pub fn get_default_language(&self) -> &str {
        &self.content.default_language
    }

    pub fn get_supported_languages(&self) -> &[String] {
        &self.content.languages
    }
}
