//! [TSM.ID].[11031972] — Platform X Ecosystem
//! xcu-bootloader — Sub-50ms parallel ecosystem initializer
#![deny(warnings)]
#![allow(dead_code)]

use std::collections::HashMap;
use std::sync::{Arc, Mutex};

#[derive(Debug)]
pub enum XcuError {
    InitFailed(String),
    InvalidConfig(String),
    OperationFailed(String),
    ResourceExhausted,
    NotFound(String),
    Timeout,
}

impl std::fmt::Display for XcuError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::InitFailed(e) => write!(f, "Init failed: {e}"),
            Self::InvalidConfig(e) => write!(f, "Invalid config: {e}"),
            Self::OperationFailed(e) => write!(f, "Operation failed: {e}"),
            Self::ResourceExhausted => write!(f, "Resource exhausted"),
            Self::NotFound(e) => write!(f, "Not found: {e}"),
            Self::Timeout => write!(f, "Operation timed out"),
        }
    }
}
impl std::error::Error for XcuError {}
pub type Result<T> = std::result::Result<T, XcuError>;

pub struct Config {
    pub params: HashMap<String, String>,
}

impl Config {
    pub fn new() -> Self { Self { params: HashMap::new() } }
    pub fn set(&mut self, key: &str, val: &str) -> &mut Self {
        self.params.insert(key.to_string(), val.to_string()); self
    }
    pub fn get(&self, key: &str) -> Result<&str> {
        self.params.get(key).map(|s| s.as_str()).ok_or_else(|| XcuError::NotFound(key.to_string()))
    }
}

impl Default for Config {
    fn default() -> Self { Self::new() }
}

pub struct Engine {
    config: Config,
    state: Arc<Mutex<EngineState>>,
}

#[derive(Debug, Clone, PartialEq)]
pub enum EngineState {
    Idle,
    Running,
    Paused,
    ShuttingDown,
    Stopped,
}

impl Engine {
    pub fn new(config: Config) -> Result<Self> {
        Ok(Self { config, state: Arc::new(Mutex::new(EngineState::Idle)) })
    }

    pub fn start(&self) -> Result<()> {
        let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
        *s = EngineState::Running;
        Ok(())
    }

    pub fn stop(&self) -> Result<()> {
        let mut s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
        *s = EngineState::ShuttingDown;
        // graceful shutdown logic
        *s = EngineState::Stopped;
        Ok(())
    }

    pub fn state(&self) -> Result<EngineState> {
        let s = self.state.lock().map_err(|e| XcuError::OperationFailed(e.to_string()))?;
        Ok(s.clone())
    }

    pub fn config(&self) -> &Config { &self.config }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_engine_lifecycle() {
        let engine = Engine::new(Config::new()).unwrap();
        assert_eq!(engine.state().unwrap(), EngineState::Idle);
        engine.start().unwrap();
        assert_eq!(engine.state().unwrap(), EngineState::Running);
        engine.stop().unwrap();
        assert_eq!(engine.state().unwrap(), EngineState::Stopped);
    }
}
