// Commande server : point d'entrée du backend PdfEditor.
package main

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

	"pdfeditor/internal/auth"
	"pdfeditor/internal/config"
	"pdfeditor/internal/db"
	"pdfeditor/internal/handlers"
	"pdfeditor/internal/storage"
)

func main() {
	// Chargement de la configuration depuis l'environnement.
	cfg, err := config.Load()
	if err != nil {
		log.Fatalf("configuration : %v", err)
	}

	ctx := context.Background()

	// Application des migrations au démarrage.
	log.Println("application des migrations...")
	if err := db.Migrate(cfg.DatabaseURL); err != nil {
		log.Fatalf("migrations : %v", err)
	}

	// Connexion à la base (pool pgx).
	pool, err := db.Connect(ctx, cfg.DatabaseURL)
	if err != nil {
		log.Fatalf("base de données : %v", err)
	}
	defer pool.Close()

	// Initialisation du stockage des fichiers.
	store, err := storage.New(cfg.StoragePath)
	if err != nil {
		log.Fatalf("stockage : %v", err)
	}

	// Gestionnaire d'authentification.
	authMgr := auth.NewManager(cfg.JWTSecret, cfg.JWTAccessTTL, cfg.JWTRefreshTTL)

	// Construction de l'API et du routeur.
	api := handlers.New(pool, authMgr, store)
	router := api.Router(cfg.CORSOrigin)

	srv := &http.Server{
		Addr:              ":" + cfg.Port,
		Handler:           router,
		ReadHeaderTimeout: 10 * time.Second,
		// Pas de WriteTimeout court : upload/download de PDF peuvent être longs.
	}

	// Démarrage du serveur dans une goroutine pour permettre l'arrêt propre.
	go func() {
		log.Printf("serveur à l'écoute sur le port %s", cfg.Port)
		if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
			log.Fatalf("serveur : %v", err)
		}
	}()

	// Attente d'un signal d'arrêt.
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
	<-stop

	log.Println("arrêt en cours...")
	shutdownCtx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
	defer cancel()
	if err := srv.Shutdown(shutdownCtx); err != nil {
		log.Printf("arrêt forcé : %v", err)
	}
	log.Println("serveur arrêté")
}
