# Forge Services

This crate implements the service layer for the Forge application, containing the core business logic and orchestration.

## Architecture

The service layer sits between the API/Extension layer and the Repository layer:

```mermaid
graph TD
    Extension[Extension Layer]
    Services[Services Layer<br/>#40;This Module#41;]
    Repositories[Repositories Layer]
    Database[Database]

    Extension --> Services
    Services --> Repositories
    Repositories --> Database
```

## Responsibilities

- **Business Logic:** Enforces game rules and constraints.
- **Validation:** Validates input data before processing.
- **Orchestration:** Coordinates operations across multiple repositories.
- **Error Handling:** Converts technical errors into business-friendly messages.
- **Data Transformation:** Handles JSON parsing and model conversion.

## Actor Service

The `ActorService` manages player lifecycle and state.

### Key Features
- **Get-or-Create:** Automatically creates new actors with default values if they don't exist.
- **JSON Integration:** Directly accepts JSON strings for updates and creation.
- **Partial Updates:** Supports updating specific fields without overwriting the entire actor.
- **UID Protection:** Prevents modification of immutable fields like UIDs.

### Usage Example

```rust
use forge_services::ActorService;
use forge_repositories::RedisActorRepository;

// Initialize
let repo = RedisActorRepository::new(client);
let service = ActorService::new(repo);

// 1. Get Actor (creates default if missing)
let actor = service.get_actor("76561198123456789".to_string())?;

// 2. Create/Overwrite Actor
let json_data = r#"{"name": "NewPlayer", "bank": 1000.0}"#;
service.create_actor("76561198123456789".to_string(), json_data.to_string())?;

// 3. Update Actor (Partial)
let update_json = r#"{"bank": 1500.0}"#;
service.update_actor("76561198123456789".to_string(), update_json.to_string())?;

// 4. Check Existence
if service.actor_exists("76561198123456789".to_string())? {
    println!("Actor exists");
}

// 5. Delete Actor
// 5. Delete Actor
service.delete_actor("76561198123456789".to_string())?;
```

## Organization Service

The `OrgService` manages organization (guild/clan) lifecycle and member management.

### Key Features
- **Get-or-Create:** Automatically creates new organizations with default values if they don't exist.
- **Member Management:** Handles adding and removing members with validation.
- **Duplicate Prevention:** Ensures unique organization IDs and member UIDs.
- **Name Validation:** Enforces non-empty organization names.

### Usage Example

```rust
use forge_services::OrgService;
use forge_repositories::RedisOrgRepository;

// Initialize
let repo = RedisOrgRepository::new(client);
let service = OrgService::new(repo);

// 1. Get Organization (creates default if missing)
let org = service.get_org("elite_squad".to_string())?;

// 2. Create/Overwrite Organization
let json_data = r#"{"name": "Elite Squad", "description": "Best players", "leader": "76561198123456789"}"#;
service.create_org("elite_squad".to_string(), json_data.to_string())?;

// 3. Add Member
let member_json = r#"{"uid": "76561198987654321", "rank": "member"}"#;
service.add_member("elite_squad".to_string(), member_json.to_string())?;

// 4. Update Organization
let update_json = r#"{"description": "New description"}"#;
service.update_org("elite_squad".to_string(), update_json.to_string())?;

// 5. Check Existence
if service.org_exists("elite_squad".to_string())? {
    println!("Organization exists");
}
```

## Error Handling

The service layer returns `Result<T, String>` where the error string is a descriptive message suitable for logging or displaying to administrators. It wraps lower-level repository errors with additional context.

## Contributing

We welcome contributions to the Forge Service Layer! This guide will help you understand how to add new services and maintain the existing codebase.

### Adding a New Service

To add a new service (e.g., `ItemService`), follow these steps:

1.  **Create the Module**: Create a new file in `src/` (e.g., `src/item.rs`).
2.  **Define the Struct**: Define your service struct with a generic repository.
    ```rust
    pub struct ItemService<R: ItemRepository> {
        repository: R,
    }
    ```
3.  **Implement `new`**: Provide a constructor that accepts the repository.
    ```rust
    impl<R: ItemRepository> ItemService<R> {
        pub fn new(repository: R) -> Self {
            Self { repository }
        }
    }
    ```
4.  **Implement Business Logic**: Add methods for your business logic (e.g., `create_item`, `transfer_item`).
    ```rust
    impl<R: ItemRepository> ItemService<R> {
        pub fn create_item(&self, item_id: String, data: String) -> Result<Item, String> {
            // Validation logic...
            if self.repository.exists(&item_id)? {
                return Err("Item already exists".to_string());
            }
            // ... logic to create item
            let item = Item::new(item_id);
            self.repository.create(&item)?;
            Ok(item)
        }
    }
    ```
5.  **Register the Module**: Add your new module to `src/lib.rs` and export the service struct.
    ```rust
    pub mod item;
    pub use item::ItemService;
    ```

### Testing

- **Unit Tests**: Write unit tests for your business logic.
- **Mocking**: Since services use generic repositories, you can easily mock them for testing without a real database.
    ```rust
    // Example Mock
    struct MockRepo;
    impl ItemRepository for MockRepo { ... }
    ```

### Best Practices

- **Validation**: Always validate data at the service boundary. Do not rely on the API layer or database constraints alone.
- **Error Messages**: Return user-friendly error messages. Avoid exposing internal database errors directly.
- **Immutability**: Respect immutable fields (like UIDs).
- **Documentation**: Document public methods with doc comments (`///`) explaining their purpose, arguments, and return values.
