package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/joho/godotenv"
	"go.uber.org/zap"

	"veza-backend-api/internal/api"
	// TODO: Réactiver internal/api/handlers après stabilisation du noyau
	// "veza-backend-api/internal/api/handlers"
	"veza-backend-api/internal/config"
	// TODO: Réactiver services après stabilisation du noyau
	// "veza-backend-api/internal/services"
)

// @title           Veza Backend API
// @version         1.2.0
// @description     Backend API for Veza platform.
// @termsOfService  http://swagger.io/terms/
// @contact.name    API Support
// @contact.url     http://www.veza.app/support
// @contact.email   support@veza.app
// @license.name    Apache 2.0
// @license.url     http://www.apache.org/licenses/LICENSE-2.0.html
// @host            localhost:8080
// @BasePath        /api/v1
// @securityDefinitions.apikey BearerAuth
// @in header
// @name Authorization
// @description Type "Bearer" followed by a space and JWT token.
func main() {
	// Charger les variables d'environnement depuis le fichier .env
	if err := godotenv.Load(); err != nil {
		log.Printf("⚠️ Impossible de charger le fichier .env: %v", err)
	}

	// Configuration du logger
	logger, err := zap.NewProduction()
	if err != nil {
		log.Fatalf("Impossible d'initialiser le logger: %v", err)
	}
	defer logger.Sync()

	logger.Info("🚀 Démarrage du serveur Veza Backend API (Architecture Moderne)")

	// Charger la configuration
	cfg, err := config.NewConfig()
	if err != nil {
		logger.Fatal("❌ Impossible de charger la configuration", zap.Error(err))
	}

	// Valider la configuration
	if err := cfg.Validate(); err != nil {
		logger.Fatal("❌ Configuration invalide", zap.Error(err))
	}

	logger.Info("✅ Configuration validée avec succès")

	// La base de données est déjà initialisée dans config.NewConfig()
	db := cfg.Database
	if db == nil {
		logger.Fatal("❌ Base de données non initialisée")
	}
	defer db.Close()

	// Initialiser la base de données (migrations, etc.)
	if err := db.Initialize(); err != nil {
		logger.Fatal("❌ Impossible d'initialiser la base de données", zap.Error(err))
	}

	// TODO: Réactiver les services après stabilisation du noyau et alignement des signatures
	// Initialiser les services
	// authService := services.NewAuthService(db, &cfg.JWT, logger)
	// oauthService := services.NewOAuthService(db, cfg, logger)
	// chatService := services.NewChatService(db, logger)
	// twoFactorService := services.NewTwoFactorService(db, logger)
	// rbacService := services.NewRBACService(db, logger)

	// TODO: Réactiver les handlers après stabilisation du noyau et alignement des services
	// Initialiser les handlers
	// handlers.InitHandlers(authService, logger)
	// handlers.InitOAuthHandlers(oauthService, authService, logger)
	// handlers.InitChatHandlers(chatService, logger)
	// handlers.InitTwoFactorHandlers(twoFactorService, authService, logger)
	// handlers.InitRBACHandlers(rbacService, logger)

	// Configuration de Gin selon l'environnement
	gin.SetMode(gin.DebugMode) // TODO: Utiliser cfg.LogLevel pour déterminer le mode

	// Créer le router Gin
	router := gin.New()

	// Configuration des routes avec la nouvelle architecture
	apiRouter := api.NewAPIRouter(db, cfg) // Instantiate APIRouter
	if err := apiRouter.Setup(router); err != nil {
		logger.Fatal("❌ Erreur lors de la configuration des routes", zap.Error(err))
	}

	// Configuration du serveur HTTP
	port := fmt.Sprintf("%d", cfg.AppPort)
	if port == "0" {
		port = "8080"
	}
	server := &http.Server{
		Addr:    fmt.Sprintf(":%s", port),
		Handler: router,
		// TODO: Ajouter ReadTimeout et WriteTimeout si nécessaire
	}

	// Canal pour écouter les signaux du système
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

	// Démarrer le serveur dans une goroutine
	go func() {
		logger.Info("🌐 Serveur HTTP démarré",
			zap.String("port", port),
		)

		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			logger.Fatal("❌ Erreur du serveur HTTP", zap.Error(err))
		}
	}()

	logger.Info("✅ Serveur Veza Backend API prêt à recevoir des requêtes")
	logger.Info("📋 Endpoints disponibles:")
	logger.Info("  - GET  /health                    - Health check global")
	logger.Info("  - POST /api/v1/auth/register     - Inscription utilisateur")
	logger.Info("  - POST /api/v1/auth/login        - Connexion utilisateur")
	logger.Info("  - POST /api/v1/auth/refresh      - Renouvellement de token")
	logger.Info("  - POST /api/v1/auth/logout       - Déconnexion utilisateur")
	logger.Info("  - GET  /api/v1/profile           - Profil utilisateur")
	logger.Info("  - PUT  /api/v1/profile           - Mise à jour profil")
	logger.Info("  - GET  /api/v1/health/detailed   - Health check détaillé")

	// Attendre un signal d'arrêt
	<-quit
	logger.Info("🔄 Arrêt du serveur en cours...")

	// Créer un contexte avec timeout pour l'arrêt gracieux
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // TODO: Utiliser config pour timeout
	defer cancel()

	// Arrêt gracieux du serveur
	if err := server.Shutdown(ctx); err != nil {
		logger.Error("❌ Erreur lors de l'arrêt du serveur", zap.Error(err))
	} else {
		logger.Info("✅ Serveur arrêté proprement")
	}
}
