# Veza Common Library

Bibliothèque commune pour tous les services Veza. Cette bibliothèque fournit des types partagés, des utilitaires et des configurations communes utilisées par tous les services du projet Veza.

## Installation

Ajoutez cette dépendance à votre `Cargo.toml`:

```toml
[dependencies]
veza-common = { path = "../veza-common" }
```

## Modules

### Types (`types`)

Types de données partagés pour tous les services.

#### User

```rust
use veza_common::types::User;

let user = User::new(1, "john_doe".to_string(), "john@example.com".to_string());
assert!(user.validate().is_ok());
```

#### Track

```rust
use veza_common::types::Track;
use uuid::Uuid;

let track_id = Uuid::new_v4();
let track = Track::new(
    track_id,
    "Song Title".to_string(),
    "Artist Name".to_string(),
    180 // duration in seconds
);
assert_eq!(track.formatted_duration(), "3:00");
```

#### Playlist

```rust
use veza_common::types::Playlist;
use uuid::Uuid;

let playlist_id = Uuid::new_v4();
let owner_id = Uuid::new_v4();
let mut playlist = Playlist::new(playlist_id, "My Playlist".to_string(), owner_id);

let track_id = Uuid::new_v4();
playlist.add_track(track_id);
assert_eq!(playlist.track_count(), 1);
```

#### API Response

```rust
use veza_common::types::ApiResponse;

// Success response
let response = ApiResponse::success("data".to_string());
assert!(response.success);

// Error response
let error_response = ApiResponse::<String>::error("Error message".to_string());
assert!(!error_response.success);
```

### Error Handling (`error`)

Types d'erreurs standardisés avec codes HTTP et messages.

```rust
use veza_common::error::{CommonError, CommonResult};

fn example_function() -> CommonResult<i32> {
    // Return success
    Ok(42)
    
    // Or error
    // Err(CommonError::NotFound("Resource not found".to_string()))
}

// Error codes
let error = CommonError::ValidationError("Invalid input".to_string());
assert_eq!(error.code(), "VALIDATION_ERROR");
assert_eq!(error.http_status_code(), 400);
```

### Configuration (`config`)

Types de configuration pour Database et Redis.

#### DatabaseConfig

```rust
use veza_common::config::DatabaseConfig;
use std::time::Duration;

let config = DatabaseConfig::new(
    "postgresql://user:password@localhost:5432/mydb".to_string(),
    10 // max_connections
);

// Validate configuration
assert!(config.validate().is_ok());

// Extract information
let host = config.host(); // Some("localhost")
let port = config.port(); // Some(5432)
let db_name = config.database_name(); // Some("mydb")
```

#### RedisConfig

```rust
use veza_common::config::RedisConfig;

let config = RedisConfig::new("redis://localhost:6379".to_string());

// Validate configuration
assert!(config.validate().is_ok());

// Check SSL
let is_ssl = config.is_ssl(); // false for redis://, true for rediss://

// Extract information
let host = config.host(); // Some("localhost")
let port = config.port(); // Some(6379)
```

### Utilities (`utils`)

#### Validation

```rust
use veza_common::utils::validation::*;

// Email validation
assert!(validate_email("test@example.com"));
assert!(!validate_email("invalid-email"));

// Username validation
assert!(validate_username("user123"));
assert!(!validate_username("ab")); // Too short

// Password validation
assert!(validate_password("Password123"));
assert!(!validate_password("short")); // Too short

// With Result return
let result = validate_email_result("test@example.com");
assert!(result.is_ok());
```

#### Serialization

```rust
use veza_common::utils::serialization::*;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct MyStruct {
    name: String,
    value: i32,
}

let data = MyStruct {
    name: "test".to_string(),
    value: 42,
};

// Serialize to JSON
let json = to_json(&data).unwrap();

// Deserialize from JSON
let deserialized: MyStruct = from_json(&json).unwrap();
assert_eq!(data, deserialized);

// Pretty print
let pretty = to_json_pretty(&data).unwrap();
```

#### Date Utilities

```rust
use veza_common::utils::date::*;
use chrono::{DateTime, Utc, Duration};

// Format timestamp
let timestamp = 1609459200; // 2021-01-01 00:00:00 UTC
let formatted = format_timestamp(timestamp);

// Parse date
let date_str = "2021-01-01T00:00:00Z";
let dt: DateTime<Utc> = parse_date(date_str).unwrap();

// Relative time
let now = Utc::now();
let past = now - Duration::hours(2);
let relative = format_relative_time(&past, &now); // "2 hours ago"

// Current timestamp
let ts = current_timestamp();
```

#### Logging

```rust
use veza_common::utils::logging::*;
use std::collections::HashMap;

// Simple logging
log_info("api", "Service started");
log_error("api", "Connection failed", None);

// Request logging
log_request("api", "GET", "/users");

// Request with context
let mut context = HashMap::new();
context.insert("user_id".to_string(), "123".to_string());
log_request_with_context("api", "POST", "/users", &context);

// Structured logging
let entry = StructuredLogEntry::new("api", "INFO", "User created")
    .with_context("user_id".to_string(), "123".to_string());
let json = entry.to_json();
```

#### General Utilities

```rust
use veza_common::utils::*;

// Generate UUID
let uuid = generate_uuid();

// Format duration
let formatted = format_duration(125); // "2:05"

// Format file size
let size = format_file_size(1024); // "1.00 KB"
```

## Exemples d'Usage Complets

### Exemple 1: Créer et valider un utilisateur

```rust
use veza_common::types::User;
use veza_common::utils::validation::validate_email_result;

fn create_user(username: String, email: String) -> Result<User, String> {
    // Validate email
    validate_email_result(&email)?;
    
    // Create user
    let user = User::new(1, username, email);
    
    // Validate user data
    user.validate()?;
    
    Ok(user)
}
```

### Exemple 2: Configuration de base de données

```rust
use veza_common::config::DatabaseConfig;
use veza_common::error::CommonResult;

fn setup_database() -> CommonResult<DatabaseConfig> {
    let config = DatabaseConfig::new(
        std::env::var("DATABASE_URL")
            .unwrap_or_else(|_| "postgresql://localhost/mydb".to_string()),
        20
    );
    
    // Validate configuration
    config.validate()?;
    
    Ok(config)
}
```

### Exemple 3: API Response avec pagination

```rust
use veza_common::types::{ApiResponse, PaginatedResponse};

fn get_users(page: u32, limit: u32) -> ApiResponse<PaginatedResponse<User>> {
    let items = vec![/* ... */];
    let total = 100;
    
    let paginated = PaginatedResponse::new(items, total, page, limit);
    ApiResponse::success(paginated)
}
```

### Exemple 4: Gestion d'erreurs

```rust
use veza_common::error::{CommonError, CommonResult};

fn process_request(data: &str) -> CommonResult<String> {
    if data.is_empty() {
        return Err(CommonError::ValidationError(
            "Data cannot be empty".to_string()
        ));
    }
    
    // Process data...
    Ok("processed".to_string())
}
```

## Tests

La bibliothèque inclut une infrastructure de tests complète dans `tests/common_tests.rs` avec:

- **Fixtures**: Fonctions pour créer des données de test
- **Helpers**: Fonctions utilitaires pour les tests
- **Exemples**: Tests d'intégration complets

Exécuter les tests:

```bash
cargo test
```

## Documentation API

Pour générer la documentation complète:

```bash
cargo doc --open
```

## Structure du Projet

```
veza-common/
├── src/
│   ├── lib.rs          # Module principal
│   ├── types/          # Types partagés (User, Track, Playlist)
│   ├── error.rs        # Gestion d'erreurs
│   ├── config/         # Configurations (Database, Redis)
│   └── utils/          # Utilitaires
│       ├── validation.rs
│       ├── serialization.rs
│       ├── date.rs
│       └── logging.rs
├── tests/
│   └── common_tests.rs # Tests d'intégration
└── Cargo.toml
```

## Licence

MIT

## Contribution

Les contributions sont les bienvenues ! Veuillez suivre les standards de code définis dans `ORIGIN_CODE_STANDARDS.md`.

