# Application

La couche Application orchestre les actions du système. Elle ne contient **aucune logique métier** (c'est le rôle du Domain) et **aucune implémentation technique** (c'est le rôle de l'Infrastructure).

Elle sert de chef d'orchestre : elle reçoit une intention, interroge le Domain, appelle les services nécessaires via des interfaces, et retourne un résultat.

---

## Structure

```
Application/
├── Command/         → Objets de commande (données en entrée d'un Use Case)
│   ├── Api/
│   └── Back/
├── Port/            → Interfaces que l'Infrastructure doit implémenter
│   ├── Repository/  → Contrats d'accès aux données
│   └── Service/     → Contrats de services externes (JWT, mail...)
└── UseCase/         → Un fichier = une action utilisateur
    ├── Api/         → Use Cases exposés via l'API (utilisateurs du SaaS)
    └── Back/        → Use Cases du back-office (superadmin uniquement)
```

---

## `Command/`

Les Commands sont des objets simples (DTO) qui transportent les données d'entrée vers un Use Case. Ils remplacent la liste de paramètres bruts et rendent le code plus lisible et plus facile à faire évoluer.

**Quand créer une Command ?**
Dès qu'un Use Case reçoit plus de 2-3 paramètres, on crée une Command associée.

**Exemple — `Command/Api/Auth/RegisterCommand.php` :**
```php
class RegisterCommand
{
    public function __construct(
        public readonly string $prenom,
        public readonly string $nom,
        public readonly string $email,
        public readonly string $password,
    ) {}
}
```

Le Use Case devient alors :
```php
public function execute(RegisterCommand $command): array
{
    // $command->prenom, $command->email...
}
```

### `Command/Api/`
Commands pour les actions déclenchées par les utilisateurs du SaaS via l'API.

| Fichier | Rôle |
|---|---|
| `Auth/LoginCommand.php` | Données d'entrée pour la connexion (email, password) |
| `Auth/RegisterCommand.php` | Données d'entrée pour l'inscription (prenom, nom, email, password, telephone) |

**À créer quand on avance :**

| Fichier | Rôle |
|---|---|
| `Project/CreateProjectCommand.php` | Données pour créer un projet |
| `Project/UpdateProjectCommand.php` | Données pour modifier un projet |
| `Module/CreateModuleCommand.php` | Données pour créer un module |
| `Module/UpdateModuleCommand.php` | Données pour modifier un module |

---

### `Command/Back/`
Commands pour les actions déclenchées par le superadmin depuis le back-office.

**À créer quand on avance :**

| Fichier | Rôle |
|---|---|
| `User/BlockUserCommand.php` | Données pour bloquer un utilisateur (userId) |
| `User/DeleteUserCommand.php` | Données pour supprimer un utilisateur (userId) |
| `Settings/UpdateSettingsCommand.php` | Données pour modifier les paramètres globaux |

## `Port/`

Les Ports sont des **interfaces PHP** que la couche Application utilise pour communiquer avec l'extérieur (base de données, JWT, mail...) sans jamais connaître les implémentations concrètes.

> Règle : la couche Application n'importe jamais Doctrine, Symfony ou une lib externe. Elle passe toujours par un Port.

### `Port/Repository/`

Contrats d'accès aux données. Chaque entité du Domain qui a besoin d'être persistée aura son interface ici.

| Fichier | Rôle |
|---|---|
| `UserRepositoryInterface.php` | Accès aux utilisateurs : `findById()`, `findByEmail()`, `save()`, `delete()`, `emailExiste()` |

**À créer quand on avance :**

| Fichier | Rôle |
|---|---|
| `ProjectRepositoryInterface.php` | Accès aux projets |
| `ModuleRepositoryInterface.php` | Accès aux modules |
| `SubscriptionRepositoryInterface.php` | Accès aux abonnements |

**Exemple — `UserRepositoryInterface.php` :**
```php
interface UserRepositoryInterface
{
    public function findById(string $id): ?User;
    public function findByEmail(string $email): ?User;
    public function emailExiste(string $email): bool;
    public function save(User $user): void;
    public function delete(User $user): void;
}
```

### `Port/Service/`

Contrats de services techniques externes que l'Application utilise sans en connaître l'implémentation.

| Fichier | Rôle |
|---|---|
| `JwtServiceInterface.php` | Génère un token JWT à partir d'un objet `User` |

**À créer quand on avance :**

| Fichier | Rôle |
|---|---|
| `MailServiceInterface.php` | Envoi d'emails (confirmation, reset password...) |
| `StorageServiceInterface.php` | Upload et récupération de fichiers |
| `ExportServiceInterface.php` | Génération de PDF / Word |
| `PaymentServiceInterface.php` | Gestion des paiements (Stripe...) |

**Exemple — `JwtServiceInterface.php` :**
```php
interface JwtServiceInterface
{
    public function genererToken(User $user): string;
}
```

---

## `UseCase/`

Chaque fichier représente **une action précise** déclenchée par l'utilisateur ou le système. Un Use Case :

1. Reçoit les données en entrée (paramètres ou Command)
2. Vérifie les règles via les entités du Domain
3. Appelle les Ports (Repository, Service) pour persister ou récupérer des données
4. Retourne un résultat (tableau, DTO, void)

**Structure type d'un Use Case :**
```php
class MonUseCase
{
    use App\Application\Command\Api\Auth\LoginCommand;

    public function __construct(
        private UserRepositoryInterface $userRepository,
        private JwtServiceInterface $jwtService,
    ) {}

    public function execute(LoginCommand $command): array
    {
        // 1. Récupérer les données
        $user = $this->userRepository->findByEmail($command->email);

        // 2. Appliquer les règles Domain
        if (!$user->estActif()) {
            throw new \RuntimeException('Compte inactif.');
        }

        // 3. Retourner le résultat
        return ['token' => $this->jwtService->genererToken($user)];
    }
}
```

---

### `UseCase/Api/`

Use Cases utilisés par les **clients du SaaS** (utilisateurs connectés via l'API). Chaque sous-dossier correspond à un domaine fonctionnel.

#### `UseCase/Api/Auth/`

Authentification des utilisateurs.

| Fichier | Rôle |
|---|---|
| `LoginUseCase.php` | Vérifie email + password, retourne un token JWT |
| `RegisterUseCase.php` | Crée un compte utilisateur, retourne un token JWT |

**À créer :**

| Fichier | Rôle |
|---|---|
| `ForgotPasswordUseCase.php` | Envoie un email de reset password |
| `ResetPasswordUseCase.php` | Réinitialise le mot de passe via un token |

#### `UseCase/Api/Project/`

Gestion des projets (cahiers des charges) par l'utilisateur.

| Fichier attendu | Rôle |
|---|---|
| `CreateProjectUseCase.php` | Crée un nouveau projet |
| `GetProjectUseCase.php` | Récupère un projet par son ID |
| `ListProjectsUseCase.php` | Liste les projets de l'utilisateur connecté |
| `UpdateProjectUseCase.php` | Modifie un projet |
| `DeleteProjectUseCase.php` | Supprime un projet |

#### `UseCase/Api/Module/`

Gestion des modules à l'intérieur d'un projet.

| Fichier attendu | Rôle |
|---|---|
| `CreateModuleUseCase.php` | Ajoute un module à un projet |
| `UpdateModuleUseCase.php` | Modifie un module |
| `DeleteModuleUseCase.php` | Supprime un module |
| `ReorderModulesUseCase.php` | Réordonne les modules d'un projet |

#### `UseCase/Api/Export/`

Export du cahier des charges dans différents formats.

| Fichier attendu | Rôle |
|---|---|
| `ExportPdfUseCase.php` | Génère un PDF du projet |
| `ExportWordUseCase.php` | Génère un fichier Word du projet |

#### `UseCase/Api/History/`

Historique des modifications sur un projet.

| Fichier attendu | Rôle |
|---|---|
| `GetHistoryUseCase.php` | Récupère l'historique d'un projet |

#### `UseCase/Api/Subscription/`

Gestion de l'abonnement de l'utilisateur.

| Fichier attendu | Rôle |
|---|---|
| `GetSubscriptionUseCase.php` | Récupère l'abonnement actif |
| `CancelSubscriptionUseCase.php` | Annule un abonnement |

---

### `UseCase/Back/`

Use Cases utilisés par le **superadmin** depuis le back-office. Les règles sont différentes de l'API : l'admin agit sur tous les comptes, pas seulement le sien.

> Important : ces Use Cases ne sont jamais appelés par les routes `/api/`. Ils ont leurs propres controllers dans `UI/Back/`.

#### `UseCase/Back/Auth/`

Authentification admin, plus stricte que l'API.

| Fichier attendu | Rôle |
|---|---|
| `AdminLoginUseCase.php` | Login avec vérification du rôle `superadmin` + déclenchement 2FA |
| `Verify2FAUseCase.php` | Vérifie le code 2FA et retourne le token final |

> Différence avec `Api/Auth/LoginUseCase` : ici on vérifie que l'utilisateur est bien `superadmin` et on exige le 2FA avant de donner accès.

#### `UseCase/Back/User/`

Gestion de tous les utilisateurs du SaaS par l'admin.

| Fichier attendu | Rôle |
|---|---|
| `ListUsersUseCase.php` | Liste tous les utilisateurs avec filtres |
| `GetUserUseCase.php` | Récupère le détail d'un utilisateur |
| `BlockUserUseCase.php` | Bloque un compte utilisateur |
| `UnblockUserUseCase.php` | Réactive un compte bloqué |
| `DeleteUserUseCase.php` | Supprime définitivement un compte |

> Différence avec l'API : l'admin peut agir sur n'importe quel utilisateur, pas seulement le sien.

#### `UseCase/Back/Project/`

Modération des projets de tous les utilisateurs.

| Fichier attendu | Rôle |
|---|---|
| `ListAllProjectsUseCase.php` | Liste tous les projets de tous les users |
| `DeleteProjectUseCase.php` | Supprime un projet (modération) |

#### `UseCase/Back/Settings/`

Paramètres globaux de l'application.

| Fichier attendu | Rôle |
|---|---|
| `GetSettingsUseCase.php` | Récupère les paramètres globaux |
| `UpdateSettingsUseCase.php` | Met à jour les paramètres |

#### `UseCase/Back/Log/`

Consultation des logs système et des actions admin.

| Fichier attendu | Rôle |
|---|---|
| `GetLogsUseCase.php` | Liste les logs avec filtres (date, type, user...) |

---

## `config/services.yaml`

C'est le fichier qui relie les **interfaces** à leurs **implémentations concrètes**.

Quand un Use Case demande un `UserRepositoryInterface` dans son constructeur, Symfony consulte ce fichier pour savoir quoi injecter.

```yaml
App\Application\Port\Repository\UserRepositoryInterface:
    class: App\Infrastructure\Persistence\Doctrine\Repository\DoctrineUserRepository

App\Application\Port\Service\JwtServiceInterface:
    class: App\Infrastructure\Auth\JwtService
```

**À chaque nouveau Port créé**, il faut ajouter une ligne ici dans le même format :

```yaml
App\Application\Port\Service\MailServiceInterface:
    class: App\Infrastructure\Notification\MailService

App\Application\Port\Repository\ProjectRepositoryInterface:
    class: App\Infrastructure\Persistence\Doctrine\Repository\DoctrineProjectRepository
```

> Règle : une interface non déclarée ici = Symfony ne sait pas quoi injecter = erreur au démarrage.

---

## Règles à respecter

- **Un Use Case = un fichier = une action**
- **Jamais** d'import Doctrine, Symfony, ou lib externe dans cette couche
- Toujours passer par les interfaces des `Port/` pour accéder aux données ou services
- Le Domain est la seule dépendance métier autorisée
- Les Use Cases `Api/` et `Back/` ne se partagent pas, même si la logique se ressemble