package dev.lions.unionflow.server;

import io.quarkus.runtime.Quarkus;
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;
import jakarta.enterprise.context.ApplicationScoped;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.logging.Logger;

/**
 * Point d'entrée principal du serveur UnionFlow.
 *
 * <p><b>UnionFlow</b> est une plateforme de gestion associative multi-tenant
 * destinée aux organisations de solidarité (associations, mutuelles, coopératives,
 * tontines, ONG) en Afrique de l'Ouest.
 *
 * <h2>Architecture</h2>
 * <ul>
 * <li><b>Backend</b> : Quarkus 3.15.1, Java 17, Hibernate Panache</li>
 * <li><b>Base de données</b> : PostgreSQL 15 avec Flyway</li>
 * <li><b>Authentification</b> : Keycloak 23 (OIDC/OAuth2)</li>
 * <li><b>API</b> : REST (JAX-RS) + WebSocket (temps réel)</li>
 * <li><b>Paiements</b> : Wave Money CI (Mobile Money)</li>
 * </ul>
 *
 * <h2>Modules fonctionnels</h2>
 * <ul>
 * <li><b>Organisations</b> — Hiérarchie multi-niveau, types paramétrables,
 * modules activables par organisation</li>
 * <li><b>Membres</b> — Adhésion, profils, rôles/permissions RBAC,
 * synchronisation bidirectionnelle avec Keycloak</li>
 * <li><b>Cotisations &amp; Paiements</b> — Campagnes récurrentes,
 * ventilation polymorphique, intégration Wave Money</li>
 * <li><b>Événements</b> — Création, inscriptions, gestion des présences,
 * géolocalisation</li>
 * <li><b>Solidarité</b> — Demandes d'aide, propositions, matching intelligent,
 * workflow de validation multi-étapes</li>
 * <li><b>Mutuelles</b> — Épargne, crédit, tontines, suivi des tours</li>
 * <li><b>Comptabilité</b> — Plan comptable SYSCOHADA, journaux,
 * écritures automatiques, balance, grand livre</li>
 * <li><b>Documents</b> — Gestion polymorphique de pièces jointes
 * (stockage local + métadonnées)</li>
 * <li><b>Notifications</b> — Templates multicanaux (email, SMS, push),
 * préférences utilisateur, historique persistant</li>
 * <li><b>Analytics &amp; Dashboard</b> — KPIs temps réel via WebSocket,
 * métriques d'activité, tendances, rapports PDF</li>
 * <li><b>Administration</b> — Audit trail complet, tickets support,
 * suggestions utilisateurs, favoris</li>
 * <li><b>SaaS Multi-tenant</b> — Formules d'abonnement flexibles,
 * souscriptions par organisation, facturation</li>
 * <li><b>Configuration dynamique</b> — Table {@code configurations},
 * pas de hardcoding, paramétrage par organisation</li>
 * <li><b>Données de référence</b> — Table {@code types_reference}
 * entièrement CRUD-able (évite les enums Java)</li>
 * </ul>
 *
 * <h2>Inventaire technique</h2>
 * <ul>
 * <li><b>60 entités JPA</b> — {@code BaseEntity} + {@code AuditEntityListener}
 * pour audit automatique</li>
 * <li><b>46 services CDI</b> — Logique métier transactionnelle</li>
 * <li><b>37 endpoints REST</b> — API JAX-RS avec validation Bean Validation</li>
 * <li><b>49 repositories</b> — Hibernate Panache pour accès données</li>
 * <li><b>Migrations Flyway</b> — V1.0 --> V3.0 (schéma complet 60 tables)</li>
 * <li><b>Tests</b> — 1127 tests unitaires et d'intégration Quarkus</li>
 * <li><b>Couverture</b> — JaCoCo 40% minimum (cible 60%)</li>
 * </ul>
 *
 * <h2>Patterns et Best Practices</h2>
 * <ul>
 * <li><b>Clean Architecture</b> — Séparation API/Impl/Entity</li>
 * <li><b>DTO Pattern</b> — Request/Response distincts (142 DTOs dans server-api)</li>
 * <li><b>Repository Pattern</b> — Abstraction accès données</li>
 * <li><b>Service Layer</b> — Transactionnel, validation métier</li>
 * <li><b>Audit automatique</b> — EntityListener JPA pour traçabilité complète</li>
 * <li><b>Soft Delete</b> — Champ {@code actif} sur toutes les entités</li>
 * <li><b>Optimistic Locking</b> — Champ {@code version} pour concurrence</li>
 * <li><b>Configuration externalisée</b> — MicroProfile Config, pas de hardcoding</li>
 * </ul>
 *
 * <h2>Sécurité</h2>
 * <ul>
 * <li>OIDC avec Keycloak (realm: unionflow)</li>
 * <li>JWT signature côté backend (HMAC-SHA256)</li>
 * <li>RBAC avec rôles: SUPER_ADMIN, ADMIN_ORGANISATION, MEMBRE</li>
 * <li>Permissions granulaires par module</li>
 * <li>CORS configuré pour client web</li>
 * <li>HTTPS obligatoire en production</li>
 * </ul>
 *
 * @author UnionFlow Team
 * @version 3.0.0
 * @since 2025-01-29
 */
@QuarkusMain
@ApplicationScoped
public class UnionFlowServerApplication implements QuarkusApplication {

    private static final Logger LOG = Logger.getLogger(UnionFlowServerApplication.class);

    /** Port HTTP configuré (défaut: 8080). */
    @ConfigProperty(name = "quarkus.http.port", defaultValue = "8080")
    int httpPort;

    /** Host HTTP configuré (défaut: 0.0.0.0). */
    @ConfigProperty(name = "quarkus.http.host", defaultValue = "0.0.0.0")
    String httpHost;

    /** Nom de l'application. */
    @ConfigProperty(name = "quarkus.application.name", defaultValue = "unionflow-server")
    String applicationName;

    /** Version de l'application. */
    @ConfigProperty(name = "quarkus.application.version", defaultValue = "3.0.0")
    String applicationVersion;

    /** Profil actif (dev, test, prod). */
    @ConfigProperty(name = "quarkus.profile")
    String activeProfile;

    /** Version de Quarkus. */
    @ConfigProperty(name = "quarkus.platform.version", defaultValue = "3.15.1")
    String quarkusVersion;

    /**
     * Point d'entrée JVM.
     *
     * <p>Lance l'application Quarkus en mode bloquant.
     * En mode natif, cette méthode démarre instantanément (&lt; 50ms).
     *
     * @param args Arguments de ligne de commande (non utilisés)
     */
    public static void main(String... args) {
        Quarkus.run(UnionFlowServerApplication.class, args);
    }

    /**
     * Méthode de démarrage de l'application.
     *
     * <p>Affiche les informations de démarrage (URLs, configuration)
     * puis attend le signal d'arrêt (SIGTERM, SIGINT).
     *
     * @param args Arguments passés depuis main()
     * @return Code de sortie (0 = succès)
     * @throws Exception Si erreur fatale au démarrage
     */
    @Override
    public int run(String... args) throws Exception {
        logStartupBanner();
        logConfiguration();
        logEndpoints();
        logArchitecture();

        LOG.info("UnionFlow Server prêt à recevoir des requêtes");
        LOG.info("Appuyez sur Ctrl+C pour arrêter");

        // Attend le signal d'arrêt (bloquant)
        Quarkus.waitForExit();

        LOG.info("UnionFlow Server arrêté proprement");
        return 0;
    }

    /**
     * Affiche la bannière ASCII de démarrage.
     */
    private void logStartupBanner() {
        LOG.info("----------------------------------------------------------");
        LOG.info("-                                                        -");
        LOG.info("-      UNIONFLOW SERVER v" + applicationVersion + "                            ");
        LOG.info("-   Plateforme de Gestion Associative Multi-Tenant       -");
        LOG.info("-                                                        -");
        LOG.info("----------------------------------------------------------");
    }

    /**
     * Affiche la configuration active.
     */
    private void logConfiguration() {
        LOG.infof("Profil      : %s", activeProfile);
        LOG.infof("Application : %s v%s", applicationName, applicationVersion);
        LOG.infof("Java        : %s", System.getProperty("java.version"));
        LOG.infof("Quarkus     : %s", quarkusVersion);
    }

    /**
     * Affiche les URLs des endpoints principaux.
     */
    private void logEndpoints() {
        String baseUrl = buildBaseUrl();

        LOG.info("--------------------------------------------------------------");
        LOG.info("📡 Endpoints disponibles:");
        LOG.infof("   - API REST     --> %s/api", baseUrl);
        LOG.infof("   - Swagger UI   --> %s/q/swagger-ui", baseUrl);
        LOG.infof("   - Health Check --> %s/q/health", baseUrl);
        LOG.infof("   - Metrics      --> %s/q/metrics", baseUrl);
        LOG.infof("   - OpenAPI      --> %s/q/openapi", baseUrl);

        if ("dev".equals(activeProfile)) {
            LOG.infof("   - Dev UI       --> %s/q/dev", baseUrl);
            LOG.infof("   - H2 Console   --> %s/q/dev/io.quarkus.quarkus-datasource/datasources", baseUrl);
        }

        LOG.info("--------------------------------------------------------------");
    }

    /**
     * Affiche l'inventaire de l'architecture.
     */
    private void logArchitecture() {
        LOG.info("    Architecture:");
        LOG.info("   - 60 Entités JPA");
        LOG.info("   - 46 Services CDI");
        LOG.info("   - 37 Endpoints REST");
        LOG.info("   - 49 Repositories Panache");
        LOG.info("   - 142 DTOs (Request/Response)");
        LOG.info("   - 1127 Tests automatisés");
        LOG.info("--------------------------------------------------------------");
    }

    /**
     * Retourne la valeur de la variable d'environnement UNIONFLOW_DOMAIN.
     * Méthode protégée pour permettre la substitution en tests.
     *
     * @return valeur de UNIONFLOW_DOMAIN, ou null si non définie
     */
    protected String getUnionflowDomain() {
        return System.getenv("UNIONFLOW_DOMAIN");
    }

    /**
     * Construit l'URL de base de l'application.
     *
     * @return URL complète (ex: http://localhost:8080)
     */
    String buildBaseUrl() {
        // En production, utiliser le nom de domaine configuré
        if ("prod".equals(activeProfile)) {
            String domain = getUnionflowDomain();
            if (domain != null && !domain.isEmpty()) {
                return "https://" + domain;
            }
        }

        // En dev/test, utiliser localhost
        String host = "0.0.0.0".equals(httpHost) ? "localhost" : httpHost;
        return String.format("http://%s:%d", host, httpPort);
    }
}
