package main

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

	"github.com/CubeCraft-Creations/Extrudex/backend/internal/config"
	"github.com/CubeCraft-Creations/Extrudex/backend/internal/db"
	"github.com/CubeCraft-Creations/Extrudex/backend/internal/router"
	"github.com/CubeCraft-Creations/Extrudex/backend/internal/sse"
)

func main() {
	// Setup structured logging
	slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
		Level: slog.LevelInfo,
	})))

	// Load configuration
	cfg, err := config.Load()
	if err != nil {
		slog.Error("failed to load config", "error", err)
		os.Exit(1)
	}

	slog.Info("config loaded", "port", cfg.Port, "cors_origin", cfg.CorsOrigin)

	// Connect to database
	dbPool, err := db.NewPool(cfg.DatabaseURL)
	if err != nil {
		slog.Error("failed to connect to database", "error", err)
		os.Exit(1)
	}
	defer db.ClosePool(dbPool)

	slog.Info("database connected")

	// Create SSE broadcaster and start it
	sseBC := sse.NewBroadcaster(128)
	sseBC.Start()
	defer sseBC.Stop()

	slog.Info("sse broadcaster started")

	// Create router
	r := router.New(cfg, dbPool, sseBC)

	// Create HTTP server
	// WriteTimeout is 0 for SSE support — the Chi middleware.Timeout(60s)
	// handles request-level timeouts on non-SSE routes.
	server := &http.Server{
		Addr:         ":" + cfg.Port,
		Handler:      r,
		ReadTimeout:  15 * time.Second,
		WriteTimeout: 0, // disabled for SSE long-lived connections
		IdleTimeout:  60 * time.Second,
	}

	// Start server in goroutine
	go func() {
		slog.Info("server starting", "addr", server.Addr)
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			slog.Error("server error", "error", err)
			os.Exit(1)
		}
	}()

	// Wait for shutdown signal
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	slog.Info("server shutting down")

	// Graceful shutdown
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	if err := server.Shutdown(ctx); err != nil {
		slog.Error("server shutdown error", "error", err)
	}

	db.ClosePool(dbPool)
	slog.Info("server stopped")
}
