use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use tokio::sync::RwLock;
use tracing::{info, warn, error, debug};
use uuid::Uuid;

/// {{.ServiceName}}Service gère les fonctionnalités de {{.ServiceName}}
#[derive(Debug, Clone)]
pub struct {{.ServiceName}}Service {
    // Ajoutez vos dépendances ici
    data: Arc<RwLock<HashMap<String, {{.ServiceName}}Data>>>,
}

/// Données pour {{.ServiceName}}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct {{.ServiceName}}Data {
    pub id: String,
    pub name: String,
    pub created_at: chrono::DateTime<chrono::Utc>,
    pub updated_at: chrono::DateTime<chrono::Utc>,
}

/// Erreurs pour {{.ServiceName}}
#[derive(Debug, thiserror::Error)]
pub enum {{.ServiceName}}Error {
    #[error("{{.ServiceName}} not found")]
    NotFound,
    
    #[error("Invalid input: {0}")]
    InvalidInput(String),
    
    #[error("Database error: {0}")]
    DatabaseError(String),
    
    #[error("Internal error: {0}")]
    InternalError(String),
}

impl {{.ServiceName}}Service {
    /// Crée une nouvelle instance du service
    pub fn new() -> Self {
        Self {
            data: Arc::new(RwLock::new(HashMap::new())),
        }
    }
    
    /// Traite les données de {{.ServiceName}}
    pub async fn process_{{.ServiceName}}(&self, input: String) -> Result<String, {{.ServiceName}}Error> {
        info!("Processing {{.ServiceName}} with input: {}", input);
        
        // Implémentation de votre logique métier
        let result = format!("Processed: {}", input);
        
        info!("{{.ServiceName}} processed successfully: {}", result);
        Ok(result)
    }
    
    /// Crée une nouvelle entrée
    pub async fn create(&self, name: String) -> Result<{{.ServiceName}}Data, {{.ServiceName}}Error> {
        info!("Creating {{.ServiceName}} with name: {}", name);
        
        let id = Uuid::new_v4().to_string();
        let now = chrono::Utc::now();
        
        let data = {{.ServiceName}}Data {
            id: id.clone(),
            name,
            created_at: now,
            updated_at: now,
        };
        
        let mut store = self.data.write().await;
        store.insert(id, data.clone());
        
        info!("{{.ServiceName}} created successfully: {}", data.id);
        Ok(data)
    }
    
    /// Récupère une entrée par ID
    pub async fn get_by_id(&self, id: &str) -> Result<{{.ServiceName}}Data, {{.ServiceName}}Error> {
        debug!("Getting {{.ServiceName}} by ID: {}", id);
        
        let store = self.data.read().await;
        store.get(id)
            .cloned()
            .ok_or({{.ServiceName}}Error::NotFound)
    }
    
    /// Met à jour une entrée existante
    pub async fn update(&self, id: &str, name: String) -> Result<{{.ServiceName}}Data, {{.ServiceName}}Error> {
        info!("Updating {{.ServiceName}} with ID: {}", id);
        
        let mut store = self.data.write().await;
        if let Some(data) = store.get_mut(id) {
            data.name = name;
            data.updated_at = chrono::Utc::now();
            info!("{{.ServiceName}} updated successfully: {}", id);
            Ok(data.clone())
        } else {
            Err({{.ServiceName}}Error::NotFound)
        }
    }
    
    /// Supprime une entrée
    pub async fn delete(&self, id: &str) -> Result<(), {{.ServiceName}}Error> {
        info!("Deleting {{.ServiceName}} with ID: {}", id);
        
        let mut store = self.data.write().await;
        if store.remove(id).is_some() {
            info!("{{.ServiceName}} deleted successfully: {}", id);
            Ok(())
        } else {
            Err({{.ServiceName}}Error::NotFound)
        }
    }
    
    /// Liste toutes les entrées
    pub async fn list_all(&self) -> Result<Vec<{{.ServiceName}}Data>, {{.ServiceName}}Error> {
        debug!("Listing all {{.ServiceName}} entries");
        
        let store = self.data.read().await;
        Ok(store.values().cloned().collect())
    }
    
    /// Health check pour le service
    pub async fn health_check(&self) -> Result<(), {{.ServiceName}}Error> {
        debug!("{{.ServiceName}} health check");
        // Implémentation du health check
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[tokio::test]
    async fn test_create_{{.ServiceName}}() {
        let service = {{.ServiceName}}Service::new();
        let result = service.create("Test {{.ServiceName}}".to_string()).await;
        
        assert!(result.is_ok());
        let data = result.unwrap();
        assert_eq!(data.name, "Test {{.ServiceName}}");
    }
    
    #[tokio::test]
    async fn test_get_{{.ServiceName}}_by_id() {
        let service = {{.ServiceName}}Service::new();
        let created = service.create("Test {{.ServiceName}}".to_string()).await.unwrap();
        
        let result = service.get_by_id(&created.id).await;
        assert!(result.is_ok());
        
        let data = result.unwrap();
        assert_eq!(data.id, created.id);
        assert_eq!(data.name, "Test {{.ServiceName}}");
    }
    
    #[tokio::test]
    async fn test_update_{{.ServiceName}}() {
        let service = {{.ServiceName}}Service::new();
        let created = service.create("Test {{.ServiceName}}".to_string()).await.unwrap();
        
        let result = service.update(&created.id, "Updated {{.ServiceName}}".to_string()).await;
        assert!(result.is_ok());
        
        let updated = result.unwrap();
        assert_eq!(updated.name, "Updated {{.ServiceName}}");
    }
    
    #[tokio::test]
    async fn test_delete_{{.ServiceName}}() {
        let service = {{.ServiceName}}Service::new();
        let created = service.create("Test {{.ServiceName}}".to_string()).await.unwrap();
        
        let result = service.delete(&created.id).await;
        assert!(result.is_ok());
        
        let get_result = service.get_by_id(&created.id).await;
        assert!(get_result.is_err());
    }
    
    #[tokio::test]
    async fn test_health_check() {
        let service = {{.ServiceName}}Service::new();
        let result = service.health_check().await;
        assert!(result.is_ok());
    }
}
