package dev.lions.unionflow.client;

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 client web UnionFlow.
 *
 * <p><b>UnionFlow Client</b> est une interface web responsive construite avec
 * PrimeFaces 14 (thème Freya) et Quarkus 3.15.1, destinée à l'administration
 * et à la gestion des organisations de solidarité (associations, mutuelles,
 * coopératives, tontines, ONG) en Afrique de l'Ouest.
 *
 * <h2>Architecture</h2>
 * <ul>
 * <li><b>Framework UI</b> : JavaServer Faces (JSF) 4.0</li>
 * <li><b>Composants</b> : PrimeFaces 14.0.0 (thème Freya)</li>
 * <li><b>Backend</b> : Quarkus 3.15.1, Java 17</li>
 * <li><b>Authentification</b> : Keycloak 23 (OIDC/OAuth2)</li>
 * <li><b>Communication API</b> : REST Client MicroProfile</li>
 * <li><b>Internationalisation</b> : i18n avec ResourceBundle (fr, en)</li>
 * </ul>
 *
 * <h2>Modules fonctionnels</h2>
 * <ul>
 * <li><b>Dashboard</b> — Tableau de bord temps réel avec KPIs,
 * graphiques interactifs (PrimeFaces Charts)</li>
 * <li><b>Organisations</b> — CRUD hiérarchique, arborescence visuelle,
 * gestion des modules activables</li>
 * <li><b>Membres</b> — Adhésion, profils détaillés, attribution de rôles,
 * import/export CSV</li>
 * <li><b>Cotisations</b> — Campagnes récurrentes, suivi des paiements,
 * relances automatiques</li>
 * <li><b>Paiements</b> — Intégration Wave Money, historique des transactions,
 * reçus PDF</li>
 * <li><b>Événements</b> — Calendrier interactif, inscriptions en ligne,
 * gestion des présences QR code</li>
 * <li><b>Solidarité</b> — Demandes d'aide, propositions, matching intelligent,
 * workflow de validation</li>
 * <li><b>Mutuelles</b> — Épargne, crédit, tontines, plans de remboursement,
 * suivi des tours</li>
 * <li><b>Comptabilité</b> — Plan comptable SYSCOHADA, saisie d'écritures,
 * balance, grand livre, rapports PDF</li>
 * <li><b>Documents</b> — Gestionnaire de fichiers avec upload,
 * prévisualisation, catégorisation</li>
 * <li><b>Notifications</b> — Centre de notifications temps réel,
 * préférences multicanaux (email, SMS, push)</li>
 * <li><b>Administration</b> — Audit trail, logs système, tickets support,
 * suggestions utilisateurs</li>
 * <li><b>SaaS Multi-tenant</b> — Gestion des abonnements,
 * souscription aux formules, facturation</li>
 * <li><b>Paramétrage</b> — Configuration dynamique par organisation,
 * types de référence CRUD-ables</li>
 * </ul>
 *
 * <h2>Inventaire technique</h2>
 * <ul>
 * <li><b>179 pages XHTML</b> — Vues JSF avec composants PrimeFaces</li>
 * <li><b>50 Managed Beans</b> — CDI ViewScoped/SessionScoped pour logique UI</li>
 * <li><b>33 Services</b> — Couche métier côté client (validation, transformation)</li>
 * <li><b>24 REST Clients</b> — MicroProfile REST Client pour communication backend</li>
 * <li><b>Templates Facelets</b> — Layout réutilisable avec thème Freya</li>
 * <li><b>Internationalisation</b> — messages_fr.properties, messages_en.properties</li>
 * <li><b>WebSocket Client</b> — Notifications temps réel depuis backend</li>
 * </ul>
 *
 * <h2>Patterns et Best Practices</h2>
 * <ul>
 * <li><b>MVC Pattern</b> — Séparation View (XHTML) / Controller (Bean) / Model (DTO)</li>
 * <li><b>Template Method</b> — Layout maître avec ui:composition</li>
 * <li><b>Service Facade</b> — Services encapsulent les appels REST Client</li>
 * <li><b>DTO Pattern</b> — Request/Response distincts provenant de server-api</li>
 * <li><b>Lazy Loading</b> — PrimeFaces DataTable avec pagination côté serveur</li>
 * <li><b>Responsive Design</b> — PrimeFaces Flex Grid pour tous les écrans</li>
 * <li><b>Configuration externalisée</b> — MicroProfile Config, pas de hardcoding</li>
 * <li><b>Error Handling</b> — ExceptionHandler centralisé avec messages i18n</li>
 * </ul>
 *
 * <h2>Sécurité</h2>
 * <ul>
 * <li>OIDC avec Keycloak (realm: unionflow)</li>
 * <li>JWT dans HTTP-only cookies (protection XSS)</li>
 * <li>CSRF protection avec PrimeFaces ViewState</li>
 * <li>RBAC avec rôles: SUPER_ADMIN, ADMIN_ORGANISATION, MEMBRE</li>
 * <li>ViewExpiredException handling pour timeout session</li>
 * <li>HTTPS obligatoire en production</li>
 * <li>Content Security Policy headers</li>
 * </ul>
 *
 * <h2>UX/UI Features</h2>
 * <ul>
 * <li>Thème sombre/clair (Freya Premium)</li>
 * <li>Notifications push temps réel (WebSocket)</li>
 * <li>Export Excel/PDF depuis DataTables</li>
 * <li>Upload de fichiers avec prévisualisation</li>
 * <li>Validation côté client (Bean Validation + JavaScript)</li>
 * <li>Loader/Spinner sur actions longues (BlockUI)</li>
 * <li>Breadcrumb navigation contextuelle</li>
 * <li>Messages growl/sticky pour feedback utilisateur</li>
 * </ul>
 *
 * @author UnionFlow Team
 * @version 1.0.0
 * @since 2025-01-29
 */
@QuarkusMain
@ApplicationScoped
public class UnionFlowClientApplication implements QuarkusApplication {

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

    /** Port HTTP configuré (défaut: 8086). */
    @ConfigProperty(name = "quarkus.http.port", defaultValue = "8086")
    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-client")
    String applicationName;

    /** Version de l'application. */
    @ConfigProperty(name = "quarkus.application.version", defaultValue = "1.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;

    /** Version de PrimeFaces. */
    @ConfigProperty(name = "unionflow.client.primefaces.version", defaultValue = "14.0.0")
    String primefacesVersion;

    /**
     * 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(UnionFlowClientApplication.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 Client pret a recevoir des requetes");
        LOG.info("Appuyez sur Ctrl+C pour arreter");

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

        LOG.info("UnionFlow Client arrete proprement");
        return 0;
    }

    /**
     * Affiche la bannière ASCII de démarrage.
     */
    private void logStartupBanner() {
        LOG.info("--------------------------------------------------------------");
        LOG.info("-                                                            -");
        LOG.info("-      UNIONFLOW CLIENT v" + applicationVersion + "                            ");
        LOG.info("-   Interface Web 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);
        LOG.infof("PrimeFaces    : %s (theme Freya)", primefacesVersion);
        LOG.infof("JSF           : 4.0 (Jakarta Faces)");
    }

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

        LOG.info("--------------------------------------------------------------");
        LOG.info("Endpoints disponibles:");
        LOG.infof("   - Page accueil  --> %s/index.xhtml", baseUrl);
        LOG.infof("   - Login         --> %s/login.xhtml", baseUrl);
        LOG.infof("   - Dashboard     --> %s/dashboard.xhtml", baseUrl);
        LOG.infof("   - Health Check  --> %s/q/health", baseUrl);
        LOG.infof("   - Metrics       --> %s/q/metrics", baseUrl);

        if ("dev".equals(activeProfile)) {
            LOG.infof("   - Dev UI        --> %s/q/dev", baseUrl);
        }

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

    /**
     * Affiche l'inventaire de l'architecture.
     */
    private void logArchitecture() {
        LOG.info("Architecture:");
        LOG.info("   - 179 Pages XHTML");
        LOG.info("   - 50 Managed Beans (JSF)");
        LOG.info("   - 33 Services");
        LOG.info("   - 24 REST Clients");
        LOG.info("   - Templates Facelets (Layout reutilisable)");
        LOG.info("   - Internationalisation (fr, en)");
        LOG.info("--------------------------------------------------------------");
    }

    /**
     * Construit l'URL de base de l'application.
     *
     * @return URL complète (ex: http://localhost:8086)
     */
    private String buildBaseUrl() {
        // En production, utiliser le nom de domaine configuré
        if ("prod".equals(activeProfile)) {
            String domain = System.getenv("UNIONFLOW_CLIENT_DOMAIN");
            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);
    }
}
