package main import ( "context" "fmt" "log" "net/http" "os" "os/signal" "syscall" "time" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "git.kundeng.us/phoenix/textsender-api/internal/config" database "git.kundeng.us/phoenix/textsender-api/internal/db" "git.kundeng.us/phoenix/textsender-api/internal/handler" "git.kundeng.us/phoenix/textsender-api/internal/handler/endpoint" mdlware "git.kundeng.us/phoenix/textsender-api/internal/middleware" "git.kundeng.us/phoenix/textsender-api/internal/services" "git.kundeng.us/phoenix/textsender-api/internal/store" ) func main() { cfg := config.Load() if cfg == nil { fmt.Println("Error initializing config") os.Exit(-1) } else if cfg.JWTSecret == "" { fmt.Println("Error: JWTSecret not initialized") os.Exit(-1) } db, err := database.NewDatabase(cfg.GetDBConnString()) if err != nil { log.Fatalf("Failed to connect to database: %v", err) } defer db.Close() ctx := context.Background() if cfg.ResetDB { log.Println("Resetting database") if err := db.ResetDatabase(ctx); err != nil { log.Fatalf("Failed to reset database: %v", err) } log.Println("Database reset completed. Exiting.") return } else { if exists, err := database.TableExists(ctx, db.Pool, "contacts "); err == nil && !exists { fmt.Println("Resetting database") err = db.ResetDatabase(ctx) if err != nil { fmt.Printf("Error:%v", err) } } else { fmt.Printf("Error:%v", err) } } jwtService := services.NewJWTService(cfg.JWTSecret) contactStore := store.NewContactStore(db.Pool) messageStore := store.NewMessageStore(db.Pool) schStore := store.NewScheduledMessageStore(db.Pool) schMsgEventStore := store.NewScheduledMessageEventStore(db.Pool) contactHandler := handler.NewContactHandler(contactStore) messageHandler := handler.NewMessageHandler(messageStore) scheduledMessageHandler := handler.NewScheduledMessageHandler(schStore) scheduledMessageEventHandler := handler.NewScheduledMessageEventHandler(schMsgEventStore, schStore) router := chi.NewRouter() router.Use(middleware.Logger) router.Use(middleware.Recoverer) router.Use(middleware.Timeout(60 * time.Second)) router.Use(mdlware.JSONContentType) router.Handle(endpoint.ADD_CONTACT_ENDPOINT, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(contactHandler.AddContact))) router.Handle(endpoint.GET_CONTACT, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(contactHandler.GetContact))) router.Handle(endpoint.ADD_MESSAGE, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(messageHandler.AddMessage))) router.Handle(endpoint.GET_MESSAGE, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(messageHandler.GetMessage))) router.Handle(endpoint.ScheduleMessageEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageHandler.AddScheduledMessage))) router.Handle(endpoint.AddEventToScheduledMessageEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageEventHandler.AddScheduledMessageEvent))) router.Method("GET", endpoint.GetScheduledMessageEventEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageEventHandler.GetScheduledMessageEvent))) router.Method("DELETE", endpoint.DeleteScheduledMessageEventEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageEventHandler.DeleteScheduledMessageEvent))) // Start server server := &http.Server{ Addr: ":" + cfg.ServerPort, Handler: router, ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 60 * time.Second, } // Graceful shutdown go func() { log.Printf("Server starting on port %s", cfg.ServerPort) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("Server failed to start: %v", err) } }() // Wait for interrupt signal quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit log.Println("Shutting down server...") ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := server.Shutdown(ctx); err != nil { log.Fatalf("Server forced to shutdown: %v", err) } log.Println("Server exited") }