# Documentation ApiService

## 🚀 Guide pratique et exemples d'utilisation

### Aperçu rapide

L'ApiService permet de gérer vos entités via des requêtes REST simples. Voici les opérations disponibles :

- **Connexion/Déconnexion** : Authentification avec token
- **GET** : Lire des données (listes ou entités spécifiques)
- **POST** : Créer de nouvelles entités
- **PATCH** : Modifier des entités existantes
- **DELETE** : Supprimer des entités

---

## Pré requis 


```

 TODO : documentation à réaliser
 configuration : /eteko_leo_serge/v2017b/4_specific/TOOSMART10/1_action/api_public/api_main.php
 
```



## 📋 Exemples concrets avec Bruno API Client

> **⚠️ Important :** Ces exemples utilisent les routes pré-configurées dans l'environnement Eteko. 
> Assurez-vous d'avoir la structure de dossiers suivante dans Bruno :
> - **API eteko/**
>   - **public/** (méthode GET)
>   - **post/** (méthode POST) 
>   - **patch/** (méthode PATCH)
> 

### 0. **Connexion et authentification (POST)**

**🔗 Endpoint :** `POST /api/post?entity=login`

```http
POST https://ts-dev.eteko.net/maxence/toosmart/soft/www/api/post?token=0w73lsy49!al4ng@q8ce
Content-Type: application/json

{
  "entity" : "login",
  "login": "admintoosmart10",
  "password": "pass.2023!"
}
```

**✅ Réponse en cas de succès :**
```json
{
    "code": 200,
    "message": "Connexion réussie",
    "data": {
        "token": "ihz392uk32s-.mg4ls!@",
        "session_user_id": 42,
        "session_id": "abc123def456",
        "user_info": {
            "user_id": 42,
            "session_id": "abc123def456",
            "token": "ihz392uk32s-.mg4ls!@"
        }
    }
}
```

> **➤ Copiez le token retourné et utilisez-le dans toutes les requêtes suivantes.**

### 0b. **Déconnexion (POST)**

**🔗 Endpoint :** `POST /api/post?entity=logout`

```http
POST https://ts-dev.eteko.net/maxence/toosmart/soft/www/api/post?token=ihz392uk32s-.mg4ls!@
Content-Type: application/json

{
  "entity" : "logout"
}
```

**✅ Réponse en cas de succès :**
```json
{
    "code": 200,
    "message": "Déconnexion réussie",
    "data": {
        "user_id": 42,
        "logged_out_at": "2024-01-15 14:30:25"
    }
}
```

> **➤ Après déconnexion, le token devient invalide et une nouvelle connexion est nécessaire.**

### 1. **Récupération de toutes les entités theme_subjects (GET)**

**🔗 Endpoint :** `GET /api/public`

```http
GET https://ts-dev.eteko.net/maxence/toosmart/soft/www/api/public?entity=theme_subjects&token=ihz392uk32s-.mg4ls!@
```

**✅ Réponse attendue :**
```json
{
    "code": 200,
    "message": "Liste des theme_subjects",
    "data": [
        {
            "id": 1,
            "subject": "Formation sécurité",
            "priority": "HIGH",
            "status": "active"
        },
        {
            "id": 236,
            "subject": "test235",
            "priority": "MEDIUM",
            "status": "active"
        }
    ]
}
```

### 2. **Création d'une nouvelle entité theme_subjects (POST)**

**🔗 Endpoint :** `POST /api/post`

```http
POST https://ts-dev.eteko.net/maxence/toosmart/soft/www/api/post?token=0w73lsy49!al4ng@q8ce
Content-Type: application/json

{
  "entity" : "theme_subjects",
  "datas": {
    "subject" : "test232"
  }
}
```

**✅ Réponse en cas de succès :**
```json
{
    "code": 200,
    "message": "Entité 'theme_subjects' créée avec succès",
    "data": {
        "[subject]": "test232"
    }
}
```

### 3. **Mise à jour d'une entité theme_subjects (PATCH)**

**🔗 Endpoint :** `PATCH /api/patch`

```http
PATCH https://ts-dev.eteko.net/maxence/toosmart/soft/www/api/patch?token=0w73lsy49!al4ng@q8ce
Content-Type: application/json

{
  "entity" : "theme_subjects",
  "id":"236",
  "datas": {
    "subject" : "test235"
  }
}
```

**✅ Réponse en cas de succès :**
```json
{
    "code": 200,
    "message": "Entité 'theme_subjects' mise à jour avec succès",
    "data": {
        "[subject]": "test235"
    }
}
```

**❌ Réponse en cas d'erreur (entité non trouvée) :**
```json
{
    "code": 404,
    "message": "Entité 'theme_subjects' avec l'ID '236' non trouvée",
    "data": null
}
```

### 4. **Suppression d'une entité theme_subjects (DELETE)**

**🔗 Endpoint :** `POST /api/post` (avec method DELETE dans le body)

```http
POST https://ts-dev.eteko.net/maxence/toosmart/soft/www/api/post?token=ihz392uk32s-.mg4ls!@
Content-Type: application/json

{
  "entity" : "theme_subjects",
  "method" : "DELETE",
  "id": 236
}
```

**✅ Réponse en cas de succès :**
```json
{
    "code": 200,
    "message": "Entité 'theme_subjects' supprimée avec succès",
    "data": {
        "deleted_id": 236
    }
}
```

**❌ Réponse en cas d'erreur (entité non trouvée) :**
```json
{
    "code": 404,
    "message": "Entité 'theme_subjects' avec l'ID '236' non trouvée",
    "data": null
}
```

---

## 🔄 Workflow complet d'utilisation

### Séquence d'utilisation complète avec Bruno

Voici un workflow complet :

#### Étape 1 : Connexion
```http
POST https://ts-dev.eteko.net/maxence/toosmart/soft/www/api/post?token=0w73lsy49!al4ng@q8ce
Content-Type: application/json

{
  "entity" : "login",
  "login": "admintoosmart10",
  "password": "pass.2023!"
}
```

#### Étape 2 : Récupération de la liste des entités
```http
GET https://ts-dev.eteko.net/maxence/toosmart/soft/www/api/public?entity=theme_subjects&token=ihz392uk32s-.mg4ls!@
```

#### Étape 3 : Création d'une nouvelle entité
```http
POST https://ts-dev.eteko.net/maxence/toosmart/soft/www/api/post?token=0w73lsy49!al4ng@q8ce
Content-Type: application/json

{
  "entity" : "theme_subjects",
  "datas": {
    "subject" : "test232"
  }
}
```

#### Étape 4 : Mise à jour de l'entité créée
```http
PATCH https://ts-dev.eteko.net/maxence/toosmart/soft/www/api/patch?token=0w73lsy49!al4ng@q8ce
Content-Type: application/json

{
  "entity" : "theme_subjects",
  "id":"236",
  "datas": {
    "subject" : "test235"
  }
}
```

#### Étape 5 : Suppression de l'entité
```http
POST https://ts-dev.eteko.net/maxence/toosmart/soft/www/api/post?token=ihz392uk32s-.mg4ls!@
Content-Type: application/json

{
  "entity" : "theme_subjects",
  "method" : "DELETE",
  "id": 236
}
```

#### Étape 6 : Déconnexion
```http
POST https://ts-dev.eteko.net/maxence/toosmart/soft/www/api/post?token=ihz392uk32s-.mg4ls!@
Content-Type: application/json

{
  "entity" : "logout"
}
```

---

## 💡 Notes importantes pour Bruno API Client

### 1. **Gestion des tokens**
- Les tokens utilisés dans les exemples (`0w73lsy49!al4ng@q8ce`, `ihz392uk32s-.mg4ls!@`) sont des exemples réels
- Vous devez remplacer ces tokens par ceux obtenus lors de votre connexion
- Les tokens peuvent être passés en paramètre de requête ou dans le header Authorization

### 2. **Endpoints différents selon l'opération**
- **GET** : `/api/public` pour les requêtes de lecture
- **POST** : `/api/post` pour les requêtes de création et commandes spéciales
- **PATCH** : `/api/patch` pour les mises à jour
- **DELETE** : Via POST avec `"method": "DELETE"` dans le body

### 3. **Structure des réponses**
Toutes les réponses suivent le même format :
```json
{
    "code": 200|400|401|404|405|500,
    "message": "Description de l'opération",
    "data": "Données ou informations d'erreur"
}
```

### 4. **Gestion des erreurs communes**
- **401** : Token invalide ou manquant → Reconnexion nécessaire
- **404** : Entité non trouvée → Vérifier l'ID fourni
- **400** : Paramètres manquants → Vérifier les données envoyées
- **405** : Méthode non autorisée → Vérifier les permissions de l'entité

---

## 🔧 Système d'annotations

### Configuration des entités

Les entités doivent être annotées pour définir les permissions et les méthodes autorisées :

```php
/**
 * #[public(
 *      properties : ['name','email','status'],
 *      functions : ['getProfile','getStats'],
 *      methods : ['GET']
 * )]
 * 
 * #[admin(
 *      properties : ['name','email','status','password_hash','created_at'],
 *      functions : ['getProfile','getStats','getAuditLog','resetPassword'],
 *      methods : ['GET','POST','PATCH','DELETE']
 * )]
 */
class UserStructure extends BaseStructure
{
    public ?string $name;
    public ?string $email;
    public ?string $status;
    public ?string $password_hash;
    public ?DateTime $created_at;

    public function getProfile() {
        return ['profile_data' => '...'];
    }

    public function getStats() {
        return ['login_count' => 42];
    }

    public function getAuditLog() {
        return ['audit_entries' => [...]];
    }

    public function resetPassword() {
        // Logic to reset password
        return ['success' => true];
    }
}
```

### Types de ressources

- **`public`** : Accès libre, propriétés et fonctions de base, généralement lecture seule (GET)
- **`admin`** : Accès complet avec toutes les opérations CRUD (GET, POST, PATCH, DELETE)
- **Personnalisé** : Types définis selon les besoins métier avec permissions spécifiques

### Exemple d'annotation pour theme_subjects

```php
/**
 * #[public(
 *      properties : ['id','subject','priority','status'],
 *      functions : ['getCompanyData'],
 *      methods : ['GET']
 * )]
 * 
 * #[admin(
 *      properties : ['id','subject','priority','status','created_at','updated_at','internal_notes'],
 *      functions : ['getCompanyData','getRelatedSubjects','getAuditLog'],
 *      methods : ['GET','POST','PATCH','DELETE']
 * )]
 */
class ThemeSubjectsStructure extends BaseStructure
{
    public ?int $id;
    public ?string $subject;
    public ?string $priority;
    public ?string $status;
    public ?DateTime $created_at;
    public ?DateTime $updated_at;
    public ?string $internal_notes;

    public function getCompanyData() {
        return ['company_name' => 'ACME Corp'];
    }

    public function getRelatedSubjects() {
        return ['related' => [1, 3, 5]];
    }

    public function getAuditLog() {
        return ['audit_entries' => [...]];
    }
}
```

---

## 📚 Documentation technique complète

### Vue d'ensemble

La classe `ApiService` est un service de gestion d'API REST pour le système TOOSMART10. Elle fournit une interface standardisée pour accéder aux entités du système avec gestion des permissions, validation des données et exécution de fonctions métier.

### Fonctionnalités principales

#### 🔐 **Authentification et gestion de session**
- Connexion utilisateur avec génération de token
- Validation automatique des sessions
- Support des tokens Bearer et cookies
- Déconnexion et nettoyage de session

#### 🔍 **Accès aux entités (GET)**
- Récupération de listes d'entités avec pagination automatique
- Accès aux entités individuelles par identifiant

#### ✏️ **Création d'entités (POST)**

#### 🔄 **Mise à jour d'entités (PATCH)**

#### 🗑️ **Suppression d'entités (DELETE)**

#### 🔐 **Gestion des permissions**
- Système d'annotations pour contrôler l'accès aux propriétés
- Support de différents niveaux de ressources (public, admin, private, etc.)
- Validation automatique des autorisations pour chaque méthode HTTP

#### ⚙️ **Exécution de fonctions métier**
- Appel de méthodes spécifiques sur les entités
- Validation des permissions pour chaque fonction
- Gestion robuste des erreurs d'exécution

#### 📊 **Formatage standardisé**
- Réponses JSON uniformes avec codes de statut HTTP
- Messages d'erreur descriptifs
- Données sécurisées et validées

### Architecture de la classe

```php
namespace ToosmarWireframe\Services;

class ApiService extends api_login  // Hérite de la gestion d'authentification
{
    private $tsClient;              // Client d'accès aux entités
    private $annotationService;     // Service de gestion des annotations
}
```

### Authentification et sécurité

#### Architecture d'authentification

L'API utilise une architecture de sécurité à 3 niveaux :

1. **`api_secure`** : Validation des tokens et sessions
2. **`api_login`** : Gestion de la connexion et initialisation utilisateur  
3. **`ApiService`** : Point d'entrée avec gestion des endpoints de connexion

#### Processus de connexion

##### 1. **Endpoint de connexion**

**URL :** `POST /api/post?entity=login`

**Paramètres acceptés :**
```php
[
    'entity' => 'login',           // Obligatoire
    'login' => 'utilisateur',      // Obligatoire 
    'password' => 'motdepasse',    // Obligatoire (ou 'mdp', ou dans 'datas')
]
```

**Exemple de requête :**
```http
POST /api?entity=login
Content-Type: application/json

{
    "entity": "login",
    "method": "POST",
    "login": "admin@example.com",
    "password": "motdepasse123"
}
```

**Réponse en cas de succès :**
```json
{
    "code": 200,
    "message": "Connexion réussie",
    "data": {
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
        "session_user_id": 42,
        "session_id": "abc123def456",
        "user_info": {
            "user_id": 42,
            "session_id": "abc123def456",
            "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
        }
    }
}
```

**Réponse en cas d'échec :**
```json
{
    "code": 401,
    "message": "Identifiants invalides",
    "data": null
}
```

##### 1b. **Endpoint de déconnexion**

**URL :** `POST /api/post?entity=logout`

**Paramètres acceptés :**
```php
[
    'entity' => 'logout',          // Obligatoire
    'token' => 'token_actuel'      // Obligatoire (dans header, GET ou POST)
]
```

**Exemple de requête :**
```http
POST /api/post?entity=logout&token=YOUR_TOKEN
Content-Type: application/json

{
    "entity": "logout",
}
```

**Réponse en cas de succès :**
```json
{
    "code": 200,
    "message": "Déconnexion réussie",
    "data": {
        "user_id": 42,
        "logged_out_at": "2024-01-15 14:30:25"
    }
}
```

**Réponse si aucune session active :**
```json
{
    "code": 200,
    "message": "Aucune session active à déconnecter",
    "data": null
}
```

##### 2. **Utilisation du token**

Une fois connecté, utilisez le token dans vos requêtes :

**Paramètre de requête**
```http
GET /api/public?entity=theme_subjects&token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...

```

##### 3. **Validation automatique**

Pour toutes les requêtes **autres que** `entity=login`, l'API vérifie automatiquement :
- Présence du token d'authentification
- Validité du token avec la session serveur
- Correspondance de l'ID de session PHP

**Réponse en cas d'authentification manquante :**
```json
{
    "code": 401,
    "message": "Authentification requise",
    "data": null
}
```

#### Gestion des sessions

##### **Initialisation de session (côté serveur)**
```php
// Lors de la connexion réussie
$_SESSION['token'] = fwc7_api_token_generate($user->id);
$_SESSION['session_user_id'] = $user->id;
$_SESSION['session_id'] = session_id();

// Cookie pour les clients web
setcookie('bearer_token', $_SESSION['token'], time() + 3600);
```

##### **Vérification de sécurité**
```php
// Validation de chaque requête authentifiée
$secure = (
    isset($_SESSION['token']) && 
    isset($_SESSION['session_id']) &&
    $_SESSION['token'] === $client_token &&
    $_SESSION['session_id'] === $client_session
);
```

#### Gestion des erreurs d'authentification

| Code | Message | Description |
|------|---------|-------------|
| **400** | "Login et mot de passe requis" | Paramètres manquants |
| **401** | "Identifiants invalides" | Échec de l'authentification |
| **401** | "Authentification requise" | Token manquant/invalide |
| **403** | "Accès interdit - Token invalide ou manquant" | Session expirée/corrompue |
| **500** | "Erreur lors de la connexion: ..." | Erreur système |
| **200** | "Déconnexion réussie" | Logout avec session active |
| **200** | "Aucune session active à déconnecter" | Logout sans session |
| **500** | "Erreur lors de la déconnexion: ..." | Erreur système lors du logout |

### Méthodes publiques

#### `__construct($tsClient)`

Initialise le service avec le client d'entités TOOSMART.

**Paramètres :**
- `$tsClient` : Instance du client TOOSMART pour l'accès aux gestionnaires d'entités

**Exemple :**
```php
$apiService = new ApiService($ts_woox_client);
```

#### `handleRequest(array $params): array`

Point d'entrée principal pour traiter les requêtes API.

**Paramètres :**
- `$params['entity']` (string, requis) : Nom de l'entité à interroger
- `$params['method']` (string, optionnel) : Méthode HTTP ('GET' par défaut, 'POST' pour création, 'PATCH' pour modification, 'DELETE' pour suppression)
- `$params['id']` (mixed, optionnel) : Identifiant spécifique d'une entité (requis pour PATCH et DELETE, optionnel pour GET)
- `$params['filter']` (string, optionnel) : Filtre SQL pour les requêtes de liste (GET uniquement)
- `$params['ressource']` (string, optionnel) : Type de permission ('public' par défaut, GET uniquement)
- `$params['function']` (string, optionnel) : Fonctions à exécuter sur les entités (GET uniquement)
- `$params['datas']` (array, optionnel) : Données pour la création/modification d'entité (POST et PATCH uniquement)

**Retour :**
```php
[
    'code' => 200|400|404|405|500,   // Code de statut HTTP
    'message' => 'Description',      // Message descriptif
    'data' => mixed                  // Données ou informations d'erreur
]
```

**Exemples d'utilisation :**

```php
// Liste d'entités (GET)
$response = $apiService->handleRequest([
    'entity' => 'theme_subjects',
    'method' => 'GET',
    'ressource' => 'public'
]);

// Entité spécifique (GET)
$response = $apiService->handleRequest([
    'entity' => 'theme_subjects',
    'method' => 'GET',
    'id' => 123,
    'ressource' => 'public'
]);

// Création d'entité (POST)
$response = $apiService->handleRequest([
    'entity' => 'theme_subjects',
    'method' => 'POST',
    'datas' => [
        'subject' => 'Nouveau sujet',
        'priority' => 'HIGH',
        'status' => 'active'
    ]
]);

// Mise à jour d'entité (PATCH)
$response = $apiService->handleRequest([
    'entity' => 'theme_subjects',
    'method' => 'PATCH',
    'id' => 123,
    'datas' => [
        'subject' => 'Sujet modifié',
        'priority' => 'MEDIUM'
    ]
]);

// Suppression d'entité (DELETE)
$response = $apiService->handleRequest([
    'entity' => 'theme_subjects',
    'method' => 'DELETE',
    'id' => 123
]);

// Avec fonctions métier (GET)
$response = $apiService->handleRequest([
    'entity' => 'theme_subjects',
    'method' => 'GET',
    'id' => 123,
    'function' => 'getCompanyData,getRelatedSubjects'
]);

// Toutes les fonctions autorisées (GET)
$response = $apiService->handleRequest([
    'entity' => 'theme_subjects',
    'method' => 'GET',
    'id' => 123,
    'function' => 'true'
]);
```

### Méthodes privées

#### Validation

##### `validateEntity($entity): void`
Valide l'existence de l'entité dans le système.

**Exceptions :**
- `Exception` : Si l'entité est manquante ou inexistante

##### `getEntityFields(string $entity, string $ressource): array`
Récupère les champs autorisés selon les annotations.

**Retour :** Liste des noms de propriétés accessibles

##### `getEntityFunctions(string $entity, string $ressource): array`
Récupère les fonctions autorisées selon les annotations.

**Retour :** Liste des noms de méthodes appelables

#### Traitement des requêtes

##### `handleGetRequest(...): array`
Traite les requêtes GET pour la récupération d'entités.

**Caractéristiques :**
- Validation de l'entité demandée
- Récupération des métadonnées (champs et fonctions autorisés)
- Routage vers le traitement approprié (liste ou entité unique)
- Application des permissions de ressource sur les propriétés
- Exécution optionnelle de fonctions sur chaque entité

##### `handlePatchRequest(string $entity, $id, array $datas): array`
Traite les requêtes PATCH pour la mise à jour d'entités.

**Caractéristiques :**
- Validation de l'entité cible et de l'ID fourni
- Vérification de l'existence de l'entité avant modification
- Transformation automatique des données (ajout de crochets autour des clés)
- Appel de la méthode `edit()` sur l'entité
- Gestion des erreurs de mise à jour et validation des données

**Format des données :**
```php
// Données d'entrée
$datas = [
    'name' => 'John Doe Updated',
    'email' => 'john.updated@example.com'
];

// Transformation automatique
$transformedDatas = [
    '[name]' => 'John Doe Updated',
    '[email]' => 'john.updated@example.com'
];
```

##### `handleDeleteRequest(string $entity, $id): array`
Traite les requêtes DELETE pour la suppression d'entités.

**Caractéristiques :**
- Validation de l'entité cible et de l'ID fourni
- Vérification de l'existence de l'entité avant suppression
- Appel de la méthode `delete()` sur l'entité
- Gestion des erreurs de suppression

**Paramètres :**
- `$entity` (string) : Nom de l'entité à supprimer
- `$id` (mixed) : Identifiant de l'entité à supprimer (requis, ne peut pas être null)

**Processus de suppression :**
1. **Validation de l'ID** : Vérification que l'ID est fourni et non vide
2. **Vérification d'existence** : Tentative de récupération de l'entité via `fetch($id)`
3. **Validation de l'entité** : Contrôle que l'entité existe réellement
4. **Suppression effective** : Appel de la méthode `delete($id)` sur l'entité
5. **Confirmation** : Retour d'une réponse de succès avec l'ID supprimé

**Gestion des erreurs spécifiques :**
- **ID manquant** : Erreur 400 si aucun ID n'est fourni
- **Entité non trouvée** : Erreur 404 si l'entité n'existe pas
- **Erreur de suppression** : Erreur 500 en cas d'échec de l'opération de suppression

**Sécurité :**
- Vérification obligatoire de l'existence avant suppression
- Pas de suppression en cascade automatique (dépend de l'implémentation de l'entité)
- Logs automatiques des erreurs avec détails techniques
- Nécessite l'autorisation DELETE dans les annotations de l'entité

**Exemple de méthode delete() attendue sur l'entité :**
```php
// Dans la classe de gestion de l'entité
public function delete($id) {
    // Validation supplémentaire métier si nécessaire
    // Gestion des contraintes référentielles
    // Suppression effective de l'entité
    // Retour true/void en cas de succès, Exception en cas d'erreur
}
```

##### `handlePostRequest(string $entity, array $datas): array`
Traite les requêtes POST pour la création d'entités.

**Caractéristiques :**
- Validation de l'entité cible
- Transformation automatique des données (ajout de crochets autour des clés)
- Appel de la méthode `create()` sur l'entité
- Gestion des erreurs de création et validation des données

**Format des données :**
```php
// Données d'entrée
$datas = [
    'name' => 'John Doe',
    'email' => 'john@example.com'
];

// Transformation automatique
$transformedDatas = [
    '[name]' => 'John Doe',
    '[email]' => 'john@example.com'
];
```

##### `handleListRequest(...): array`
Traite les requêtes de liste d'entités.

**Caractéristiques :**
- Pagination automatique (limite : 100 éléments)
- Application des filtres SQL
- Application des permissions de ressource sur les propriétés
- Exécution optionnelle de fonctions sur chaque entité

##### `handleSingleEntityRequest(...): array`
Traite les requêtes d'entité spécifique.

**Caractéristiques :**
- Validation de l'existence de l'entité
- Application des permissions de ressource
- Exécution validée des fonctions métier

#### Exécution de fonctions

##### `processFunctionParameter($function, $availableFunctions): array`
Analyse le paramètre function et retourne la liste des fonctions à exécuter.

**Formats supportés :**
- `false/null` : Aucune fonction
- `"true"` : Toutes les fonctions autorisées
- `"func1,func2"` : Liste spécifique (séparée par virgules)

##### `executeFunctions($entityObject, $functions): array`
Exécution simple pour les listes (sans validation complète).

##### `executeValidatedFunctions(...): array`
Exécution avec validation complète pour les entités spécifiques.

**Validations :**
- Autorisation de la fonction pour la ressource
- Existence de la méthode sur l'objet
- Gestion des erreurs d'exécution

#### Formatage des réponses

##### `formatSuccessResponse(string $message, $data): array`
Formate les réponses de succès avec code 200.

##### `formatErrorResponse(int $code, string $message, $data = null): array`
Formate les réponses d'erreur avec codes appropriés.

### Gestion des erreurs

#### Types d'erreurs gérées

1. **Paramètre manquant (500)**
   ```php
   ['code' => 500, 'message' => "Le paramètre 'entity' est requis"]
   ```

2. **Méthode non autorisée (405)**
   ```php
   ['code' => 405, 'message' => "Méthode non autorisée"]
   ```

3. **Données manquantes pour création/modification (400)**
   ```php
   ['code' => 400, 'message' => "Données manquantes"]
   ['code' => 400, 'message' => "Données manquantes pour la mise à jour"]
   ```

4. **ID manquant pour modification/suppression (400)**
   ```php
   ['code' => 400, 'message' => "L'ID est requis pour la mise à jour"]
   ['code' => 400, 'message' => "L'ID est requis pour la suppression"]
   ```

5. **Entité inexistante (500)**
   ```php
   [
       'code' => 500,
       'message' => "L'entité 'inexistante' n'existe pas",
       'data' => ['available_entities' => [...]]
   ]
   ```

6. **Entité non trouvée (404)**
   ```php
   ['code' => 404, 'message' => "Entité 'users' avec l'ID '999' non trouvée"]
   ```

7. **Erreur système (500)**
   ```php
   [
       'code' => 500,
       'message' => "Erreur lors de l'accès à l'entité...",
       'data' => [
           'error_type' => 'Exception',
           'error_file' => '/path/to/file.php',
           'error_line' => 123
       ]
   ]
   ```

#### Gestion des erreurs de fonctions

Les erreurs lors de l'exécution de fonctions métier sont capturées et incluses dans la réponse :

```php
[
    'code' => 200,
    'data' => [
        'id' => 123,
        'name' => 'Example',
        'functions' => [
            'validFunction' => ['result' => 'success'],
            'errorFunction' => ['error' => 'Division by zero'],
            'unauthorizedFunction' => ['error' => "Function 'secret' not allowed for resource 'public'"],
            'missingFunction' => ['error' => "Function 'nonexistent' does not exist"]
        ]
    ]
]
```

### Système d'annotations

#### Configuration des entités

Les entités doivent être annotées pour définir les permissions et les méthodes autorisées :

```php
/**
 * #[public(
 *      properties : ['name','email','status'],
 *      functions : ['getProfile','getStats'],
 *      methods : ['GET']
 * )]
 * 
 * #[admin(
 *      properties : ['name','email','status','password_hash','created_at'],
 *      functions : ['getProfile','getStats','getAuditLog','resetPassword'],
 *      methods : ['GET','POST','PATCH','DELETE']
 * )]
 */
class UserStructure extends BaseStructure
{
    public ?string $name;
    public ?string $email;
    public ?string $status;
    public ?string $password_hash;
    public ?DateTime $created_at;

    public function getProfile() {
        return ['profile_data' => '...'];
    }

    public function getStats() {
        return ['login_count' => 42];
    }

    public function getAuditLog() {
        return ['audit_entries' => [...]];
    }

    public function resetPassword() {
        // Logic to reset password
        return ['success' => true];
    }
}
```

#### Types de ressources

- **`public`** : Accès libre, propriétés et fonctions de base, généralement lecture seule (GET)
- **`admin`** : Accès complet avec toutes les opérations CRUD (GET, POST, PATCH, DELETE)
- **Personnalisé** : Types définis selon les besoins métier avec permissions spécifiques

### Exemples d'utilisation complète

#### Création d'entité (POST)

```php
$params = [
    'entity' => 'theme_subjects',
    'method' => 'POST',
    'datas' => [
        'subject' => 'Formation sécurité informatique',
        'priority' => 'HIGH',
        'status' => 'active',
        'description' => 'Formation sur les bonnes pratiques de sécurité'
    ]
];

$response = $apiService->handleRequest($params);

// Résultat en cas de succès :
[
    'code' => 200,
    'message' => "Entité 'theme_subjects' créée avec succès",
    'data' => [
        '[subject]' => 'Formation sécurité informatique',
        '[priority]' => 'HIGH',
        '[status]' => 'active',
        '[description]' => 'Formation sur les bonnes pratiques de sécurité'
    ]
]

// Résultat en cas d'erreur (données manquantes) :
[
    'code' => 400,
    'message' => 'Données manquantes',
    'data' => null
]
```

#### Mise à jour d'entité (PATCH)

```php
$params = [
    'entity' => 'theme_subjects',
    'method' => 'PATCH',
    'id' => 123,
    'datas' => [
        'subject' => 'Formation sécurité informatique - Mise à jour',
        'priority' => 'MEDIUM',
        'status' => 'updated'
    ]
];

$response = $apiService->handleRequest($params);

// Résultat en cas de succès :
[
    'code' => 200,
    'message' => "Entité 'theme_subjects' mise à jour avec succès",
    'data' => [
        '[subject]' => 'Formation sécurité informatique - Mise à jour',
        '[priority]' => 'MEDIUM',
        '[status]' => 'updated'
    ]
]

// Résultat en cas d'erreur (entité non trouvée) :
[
    'code' => 404,
    'message' => "Entité 'theme_subjects' avec l'ID '123' non trouvée",
    'data' => null
]

// Résultat en cas d'erreur (ID manquant) :
[
    'code' => 400,
    'message' => "L'ID est requis pour la mise à jour",
    'data' => null
]
```

#### Suppression d'entité (DELETE)

```php
$params = [
    'entity' => 'theme_subjects',
    'method' => 'DELETE',
    'id' => 123
];

$response = $apiService->handleRequest($params);

// Résultat en cas de succès :
[
    'code' => 200,
    'message' => "Entité 'theme_subjects' supprimée avec succès",
    'data' => [
        'deleted_id' => 123
    ]
]

// Résultat en cas d'erreur (entité non trouvée) :
[
    'code' => 404,
    'message' => "Entité 'theme_subjects' avec l'ID '123' non trouvée",
    'data' => null
]

// Résultat en cas d'erreur (ID manquant) :
[
    'code' => 400,
    'message' => "L'ID est requis pour la suppression",
    'data' => null
]
```

#### Récupération de liste avec filtres (GET)

```php
$params = [
    'entity' => 'theme_subjects',
    'method' => 'GET',
    'filter' => "status = 'active' AND priority = 'HIGH'",
    'ressource' => 'public',
    'function' => 'getCompanyData'
];

$response = $apiService->handleRequest($params);

// Résultat :
[
    'code' => 200,
    'message' => 'Liste des theme_subjects',
    'data' => [
        [
            // Seules les propriétés autorisées pour 'public' sont retournées
            'subject' => 'Sécurité informatique',
            'priority' => 'HIGH',
            // 'internal_notes' => masqué car non autorisé pour 'public'
            'functions' => [
                'getCompanyData' => ['company_name' => 'ACME Corp']
            ]
        ],
        // ... autres entités
    ]
]
```

#### Configuration des entités

Les entités doivent être annotées pour définir les permissions et les méthodes autorisées :

```php
/**
 * #[public(
 *      properties : ['name','email','status'],
 *      functions : ['getProfile','getStats'],
 *      methods : ['GET']
 * )]
 * 
 * #[admin(
 *      properties : ['name','email','status','password_hash','created_at'],
 *      functions : ['getProfile','getStats','getAuditLog','resetPassword'],
 *      methods : ['GET','POST','PATCH','DELETE']
 * )]
 */
class UserStructure extends BaseStructure
{
    public ?string $name;
    public ?string $email;
    public ?string $status;
    public ?string $password_hash;
    public ?DateTime $created_at;

    public function getProfile() {
        return ['profile_data' => '...'];
    }

    public function getStats() {
        return ['login_count' => 42];
    }

    public function getAuditLog() {
        return ['audit_entries' => [...]];
    }

    public function resetPassword() {
        // Logic to reset password
        return ['success' => true];
    }
}
```

### Bonnes pratiques

#### 1. **Validation des paramètres**
Toujours valider les paramètres avant l'appel :

```php
// Pour les requêtes GET
$params = [
    'entity' => trim($_GET['entity'] ?? ''),
    'method' => 'GET',
    'id' => filter_var($_GET['id'] ?? false, FILTER_VALIDATE_INT),
    'ressource' => in_array($_GET['ressource'] ?? 'public', ['public', 'admin']) 
                   ? $_GET['ressource'] : 'public'
];

// Pour les requêtes POST
$params = [
    'entity' => trim($_POST['entity'] ?? ''),
    'method' => 'POST',
    'datas' => array_filter($_POST['datas'] ?? [], function($value) {
        return !empty(trim($value));
    })
];

// Pour les requêtes PATCH
$params = [
    'entity' => trim($_POST['entity'] ?? ''),
    'method' => 'PATCH',
    'id' => filter_var($_POST['id'] ?? false, FILTER_VALIDATE_INT),
    'datas' => array_filter($_POST['datas'] ?? [], function($value) {
        return !empty(trim($value));
    })
];

// Pour les requêtes DELETE
$params = [
    'entity' => trim($_POST['entity'] ?? ''),
    'method' => 'DELETE',
    'id' => filter_var($_POST['id'] ?? false, FILTER_VALIDATE_INT)
];
```

#### 2. **Gestion des erreurs**
Toujours vérifier le code de retour :

```php
$response = $apiService->handleRequest($params);

if ($response['code'] !== 200) {
    // Gestion de l'erreur
    error_log("API Error: " . $response['message']);
    return $response;
}

// Traitement des données
$data = $response['data'];
```

#### 3. **Gestion de la déconnexion**
Toujours gérer proprement la déconnexion :

```php
// Pour les requêtes LOGOUT
$params = [
    'entity' => 'logout',
    'method' => 'POST',
    'token' => $current_token  // Token actuel à invalider
];

$response = $apiService->handleRequest($params);

if ($response['code'] === 200) {
    // Supprimer le token côté client
    unset($_SESSION['api_token']);
    setcookie('api_token', '', time() - 3600);
    
    // Redirection vers la page de connexion
    header('Location: /login');
} else {
    // Gestion de l'erreur de déconnexion
    error_log("Logout Error: " . $response['message']);
}
```

### Méthodes attendues sur les entités
- `getStructure()` : Retourne la structure de l'entité pour l'analyse des annotations
- `list(...)` : Méthode de récupération de liste avec pagination (GET)
- `fetch($id)` : Méthode de récupération d'entité par ID (GET, PATCH, DELETE)
- `create($datas, $mode)` : Méthode de création d'entité (POST)
- `edit($id, $datas, $mode)` : Méthode de modification d'entité (PATCH)
- `delete($id)` : Méthode de suppression d'entité (DELETE)
- `getData()` : Récupération des données de base de l'entité
- `getPropertiesValues($ressource)` : Récupération des propriétés selon les permissions

Cette documentation fournit une vue complète de l'utilisation et du fonctionnement du service ApiService pour une intégration efficace dans vos projets, incluant maintenant toutes les opérations CRUD : création (POST), lecture (GET), mise à jour (PATCH) et suppression (DELETE) d'entités.




